Syslog-ng multiline input over TCP/Network module - tcp

We are attempting to capture logs to syslog-ng over tcp connection. The logs looks something like this:
1810717353--user--notice--IPV4----2017-10-23T16:03:23.015170-04:00--<11>Oct 23 16:03:23 HOSTNAME [443-Multiplexer][0x80000001][xsltmsg][error] xmlfirewall(443-Multiplexer): trans(2607607975)[error][ip] gtid(value):
1810717354--user--notice--IPV4----2017-10-23T16:03:23.015170-04:00-- Default rule caught error code '
1810717355--user--notice--IPV4----2017-10-23T16:03:23.015170-04:00-- 0x00230001
1810717356--user--notice--IPV4----2017-10-23T16:03:23.015170-04:00-- '
1810717357--user--notice--IPV4----2017-10-23T16:03:23.015170-04:00--
1810717358--user--notice--IPV4----2017-10-23T16:03:23.015170-04:00--<14>Oct 23 16:03:23 HOSTNAME [443-Multiplexer][value][multistep][info] xmlfirewall(443-Multiplexer): trans(2607607975)[error][ip] gtid(2607607975):
Is there any way to strip out the syslog header during the input? If the logs remain multiline, thats fine, we can package them with logstash during read, but we need a way for the logs to now have a header when they are written to file ..
Here is my current syslog-ng config :
#version: 3.6
##include "scl.conf"
options {
flush_lines (0);
frac-digits(8);
use-rcptid (yes);
time_reopen (10);
log_fifo_size (1000);
chain_hostnames (off);
use_dns (no);
use_fqdn (no);
create_dirs (no);
keep_hostname (yes);
use-rcptid (yes);
threaded(yes);
log_msg_size(32768);
};
source sourcename
{
network(ip("0.0.0.0") port(5521) flags(no-parse));
};
destination destname
{
file("/opt/elk/data/syslogs/datapower/${HOST}.log"
#follow-freq(0) multi-line-mode(regexp) multi-line-prefix("^\<\[0-9]{2}\>[A-z]{3} [0-9]{2} [0-9]{2}\:[0-9]{2}\:[0-9]{2}")
create_dirs(yes) dir_owner("elkuser") dir_group("users") dir_perm(0700)
owner("user") group("group") perm(0600)
template("${RCPTID}--$FACILITY--$PRIORITY--$FULLHOST--$PROGRAM--$ISODATE--${MSGHDR}${MSG}\n")
);
};
Thanks

I'm not sure where you want to split the message, but depending on that, you can do the following:
If it is enough to delete a fix number of characters, you can use the substr template function (https://www.balabit.com/documents/syslog-ng-ose-latest-guides/en/syslog-ng-ose-guide-admin/html/reference-template-functions.html)
If you want to join the multiline messages, you might want to check the multiline options of the network source: https://www.balabit.com/documents/syslog-ng-ose-latest-guides/en/syslog-ng-ose-guide-admin/html/reference-source-network.html
If you need a lot of custom processing for these logs, it might be easier to write a custom python parser ( https://www.balabit.com/documents/syslog-ng-ose-latest-guides/en/syslog-ng-ose-guide-admin/html/python-parser.html ). Note that Python parser requires a recent version of syslog-ng.
Also, it seems that you are sending the logs to Elasticsearch somehow (at least I suspect that's what elk in the destination stands for): recent versions of syslog-ng can do that directly: https://www.balabit.com/documents/syslog-ng-ose-latest-guides/en/syslog-ng-ose-guide-admin/html/configuring-destinations-elasticsearch2.html
HTH,
Robert

Related

nginx module: compiles but fails to link a new library

I have modified an nginx module in a way that it depends on a library.... let's call the library that I need libx.
I have modified auto/os/linux in such a way that I am able to detect if libx is present... by adding something like:
+ngx_feature="libx"
+ngx_feature_name="NGX_HAVE_LIBX"
+ngx_feature_run=no
+ngx_feature_incs="#include <libx.h>"
+ngx_feature_path=
+ngx_feature_libs=-lx
+ngx_feature_test="libx_init();"
+. auto/feature
Then, in the module code I do #ifs checking for NGX_HAVE_LIBX... something like:
#if (NGX_HAVE_LIBX)
libx_init();
#endif
And it works like a charm.... when I run auto/configure I get that the library is detected with something like:
checking for libx... found
and it compiles BUT at link time it's not including -lx as part of the flags sent to cc/ld when building the final objs/nginx binary. I would have expected that after the feature be detected in auto/os/linux it would automagically be added to the linking phase when creating the Makefile... but apparently that's not the case so I know I am missing something... what additional step do I need to do to pull it off?
This is on nginx 1.19.2 (well, master branch from nginx mirror).
I think I got it.
I needed to add something like this:
+ngx_feature="libx"
+ngx_feature_name="NGX_HAVE_LIBX"
+ngx_feature_run=no
+ngx_feature_incs="#include <libx.h>"
+ngx_feature_path=
+ngx_feature_libs=-lx
+ngx_feature_test="libx_init();"
+. auto/feature
if [ $ngx_found = yes ]; then
CORE_LIBS="$CORE_LIBS -lx"
NGX_LIBDL="-lx"
fi

Has there ever been a unix system call to create a link from an open file descriptor? [duplicate]

In Unix, it's possible to create a handle to an anonymous file by, e.g., creating and opening it with creat() and then removing the directory link with unlink() - leaving you with a file with an inode and storage but no possible way to re-open it. Such files are often used as temp files (and typically this is what tmpfile() returns to you).
My question: is there any way to re-attach a file like this back into the directory structure? If you could do this it means that you could e.g. implement file writes so that the file appears atomically and fully formed. This appeals to my compulsive neatness. ;)
When poking through the relevant system call functions I expected to find a version of link() called flink() (compare with chmod()/fchmod()) but, at least on Linux this doesn't exist.
Bonus points for telling me how to create the anonymous file without briefly exposing a filename in the disk's directory structure.
A patch for a proposed Linux flink() system call was submitted several years ago, but when Linus stated "there is no way in HELL we can do this securely without major other incursions", that pretty much ended the debate on whether to add this.
Update: As of Linux 3.11, it is now possible to create a file with no directory entry using open() with the new O_TMPFILE flag, and link it into the filesystem once it is fully formed using linkat() on /proc/self/fd/fd with the AT_SYMLINK_FOLLOW flag.
The following example is provided on the open() manual page:
char path[PATH_MAX];
fd = open("/path/to/dir", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
/* File I/O on 'fd'... */
snprintf(path, PATH_MAX, "/proc/self/fd/%d", fd);
linkat(AT_FDCWD, path, AT_FDCWD, "/path/for/file", AT_SYMLINK_FOLLOW);
Note that linkat() will not allow open files to be re-attached after the last link is removed with unlink().
My question: is there any way to re-attach a file like this back into the directory structure? If you could do this it means that you could e.g. implement file writes so that the file appears atomically and fully formed. This appeals to the my compulsive neatness. ;)
If this is your only goal, you can achieve this in a much simpler and more widely used manner. If you are outputting to a.dat:
Open a.dat.part for write.
Write your data.
Rename a.dat.part to a.dat.
I can understand wanting to be neat, but unlinking a file and relinking it just to be "neat" is kind of silly.
This question on serverfault seems to indicate that this kind of re-linking is unsafe and not supported.
Thanks to #mark4o posting about linkat(2), see his answer for details.
I wanted to give it a try to see what actually happened when trying to actually link an anonymous file back into the filesystem it is stored on. (often /tmp, e.g. for video data that firefox is playing).
As of Linux 3.16, there still appears to be no way to undelete a deleted file that's still held open. Neither AT_SYMLINK_FOLLOW nor AT_EMPTY_PATH for linkat(2) do the trick for deleted files that used to have a name, even as root.
The only alternative is tail -c +1 -f /proc/19044/fd/1 > data.recov, which makes a separate copy, and you have to kill it manually when it's done.
Here's the perl wrapper I cooked up for testing. Use strace -eopen,linkat linkat.pl - </proc/.../fd/123 newname to verify that your system still can't undelete open files. (Same applies even with sudo). Obviously you should read code you find on the Internet before running it, or use a sandboxed account.
#!/usr/bin/perl -w
# 2015 Peter Cordes <peter#cordes.ca>
# public domain. If it breaks, you get to keep both pieces. Share and enjoy
# Linux-only linkat(2) wrapper (opens "." to get a directory FD for relative paths)
if ($#ARGV != 1) {
print "wrong number of args. Usage:\n";
print "linkat old new \t# will use AT_SYMLINK_FOLLOW\n";
print "linkat - <old new\t# to use the AT_EMPTY_PATH flag (requires root, and still doesn't re-link arbitrary files)\n";
exit(1);
}
# use POSIX qw(linkat AT_EMPTY_PATH AT_SYMLINK_FOLLOW); #nope, not even POSIX linkat is there
require 'syscall.ph';
use Errno;
# /usr/include/linux/fcntl.h
# #define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links. */
# #define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */
# #define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */
unless (defined &AT_SYMLINK_NOFOLLOW) { sub AT_SYMLINK_NOFOLLOW() { 0x0100 } }
unless (defined &AT_SYMLINK_FOLLOW ) { sub AT_SYMLINK_FOLLOW () { 0x0400 } }
unless (defined &AT_EMPTY_PATH ) { sub AT_EMPTY_PATH () { 0x1000 } }
sub my_linkat ($$$$$) {
# tmp copies: perl doesn't know that the string args won't be modified.
my ($oldp, $newp, $flags) = ($_[1], $_[3], $_[4]);
return !syscall(&SYS_linkat, fileno($_[0]), $oldp, fileno($_[2]), $newp, $flags);
}
sub linkat_dotpaths ($$$) {
open(DOTFD, ".") or die "open . $!";
my $ret = my_linkat(DOTFD, $_[0], DOTFD, $_[1], $_[2]);
close DOTFD;
return $ret;
}
sub link_stdin ($) {
my ($newp, ) = #_;
open(DOTFD, ".") or die "open . $!";
my $ret = my_linkat(0, "", DOTFD, $newp, &AT_EMPTY_PATH);
close DOTFD;
return $ret;
}
sub linkat_follow_dotpaths ($$) {
return linkat_dotpaths($_[0], $_[1], &AT_SYMLINK_FOLLOW);
}
## main
my $oldp = $ARGV[0];
my $newp = $ARGV[1];
# link($oldp, $newp) or die "$!";
# my_linkat(fileno(DIRFD), $oldp, fileno(DIRFD), $newp, AT_SYMLINK_FOLLOW) or die "$!";
if ($oldp eq '-') {
print "linking stdin to '$newp'. You will get ENOENT without root (or CAP_DAC_READ_SEARCH). Even then doesn't work when links=0\n";
$ret = link_stdin( $newp );
} else {
$ret = linkat_follow_dotpaths($oldp, $newp);
}
# either way, you still can't re-link deleted files (tested Linux 3.16 and 4.2).
# print STDERR
die "error: linkat: $!.\n" . ($!{ENOENT} ? "ENOENT is the error you get when trying to re-link a deleted file\n" : '') unless $ret;
# if you want to see exactly what happened, run
# strace -eopen,linkat linkat.pl
Clearly, this is possible -- fsck does it, for example. However, fsck does it with major localized file system mojo and will clearly not be portable, nor executable as an unprivileged user. It's similar to the debugfs comment above.
Writing that flink(2) call would be an interesting exercise. As ijw points out, it would offer some advantages over current practice of temporary file renaming (rename, note, is guaranteed atomic).
Kind of late to the game but I just found http://computer-forensics.sans.org/blog/2009/01/27/recovering-open-but-unlinked-file-data which may answer the question. I haven't tested it, though, so YMMV. It looks sound.

Silencing ChromeDriver.exe logging

I am running ruby unit tests against Chrome using watir-webdriver. Whenever a test is run and chromedriver.exe is launched output similar to below appears:
Started ChromeDriver
port=9515
version=26.0.1383.0
log=C:\Home\Server\Test\Watir\web\chromedriver.log
[5468:8796:0404/150755:ERROR:accelerated_surface_win.cc(208)] Reseting D3D device
[5468:8996:0404/150758:ERROR:textfield.h(156)] NOT IMPLEMENTED
[WARNING:..\..\..\..\flash\platform\pepper\pep_module.cpp(63)] SANDBOXED
None of this impacts the correct functioning of the tests, but as one might imagine the appearance of "ERROR" and "WARNING" might be rather confusing to, for example, parsing rules in Jenkins looking for failures. Sure I can get really fancy with regular expression in the parsing rules, but it would be really nice to turn off this verbose and unnecessary logging on the part of chromedriver.exe. I have seen many mentions of this searching for an answer. No one has come up with a solution. Yes, chromedriver possibly has a "--silent" option, but there seems to be no way to pass that to the executable. Code similar to below is supposed to work, but has zero effect as far as I can see. Any ideas?
profile = Selenium::WebDriver::Chrome::Profile.new
profile['--cant-make-any-switches-work-here-how-about-you'] = true
browser = Watir::Browser.new :chrome, :profile => profile, :switches => %w[--ignore-certificate-errors --disable-extensions --disable-popup-blocking --disable-translate--allow-file-access]
Here's help for anyone else searching
Find ...selenium\webdriver\chrome\service.rb
Path start may differ on your system
And I added "-silent" to the passed parameters .... However, this silenced everything but the error/warning messages.
def initialize(executable_path, port)
#uri = URI.parse "http://#{Platform.localhost}:#{port}"
server_command = [executable_path, " -silent", "--port=#{port}"]
#process = ChildProcess.build(*server_command)
#socket_poller = SocketPoller.new Platform.localhost, port, START_TIMEOUT
#process.io.inherit! if $DEBUG == true
end
set chromeOptions with key --log-level=3 this should shut it up
I was able to divert the hundreds, yes hundreds, of chrome driver log messages that were showing up in cucumber stdout by using the :service_log_path argument.
#browser = Watir::Browser.new :chrome, :service_log_path => 'chromedriver.out'
the '-silent', or '--silent', or ' -silent', or ' --silent' parameter suggested above did nothing when I added it to ...selenium\webdriver\chrome\service.rb. And having to tweak the gem itself is not a particularly viable solution.
I couldn't find a place to capture the chromedriver stderr and divert it to null (not to mention having to handle doing that in windows and in *nix/osx)
The driver should default to something way less verbose. In this case INFO is way too verbose as hundreds of log entries pop out as INFO, 90%+ of them identical.
At least the :service_log_path argument works most of them.
You can try -Dwebdriver.chrome.logfile="/dev/null" and/or -Dwebdriver.chrome.args="--disable-logging" to the options of java that runs selenium-server-standalone-what.ever.jar

How do you transfer a binary file via Connect:Direct NDM?

I'm trying to submit a binary file, in this case, an Excel file from my local server (Solaris server with Mainframe rehosting software) using Connect:Direct NDM to a destination server (Mainframe).
Here are the environment values I set:
SODETFL "DetailedReport.xls"
SODDETNDM "FIN.REPORT(+1)"
TDCOPTS ":DATATYPE=BINARY:XLATE=NO:STRIP.BLANKS=NO"
Here is the NDM configuration I use:
ASSGNDD ddname='SYSIN' type='INSTREAM' << !
SIGNON 00260005
SUBMIT PROC=COPYFILE - 00270005
JOBNAME=JOB00001 - 00280005
PNODE=SERVER001 - 00290005
SNODE=NDMIDS - 00300005
SNODEID=(xxxxxx,xxxxxx) - 00310005
HOLD=NO - 00320005
NOTIFY=CCACTD - 00330005
NODE=, - 00360005
DSN1=${SODDETFL} - 00370005
DSN2=${SODDETNDM} -
DCBINFO='dcb=(dsorg=ps, recfm=vb, lrecl=1504)' - 00385005
DISP1=NEW, - 00390005
DISP2=CATLG,DELETE - 00400005
UNIT=BATCH - 00410005
SYSOPTS=${TDCOPTS} - 00440005
AEFAJOB=PSIAPNB5
SEL PROC WHERE (QUEUE=A) TABLE 00450005
SIGNOFF 00460005
I'm able to send text files via NDM all day long, no problems there. However, it seems that binary is a bit more difficult. When I try with the above configuration, I get the following error:
Completion Code => 8
Message Id => XCPS009I
Short Text => Read buffer too small. Possibly src reclen > dest reclen.
Ckpt=>Y Lkfl=>N Rstr=>N Xlat=>Y Scmp=>N Ecmp=>Y Ecpr=>0.00 CRC=>N Zlvl=>1 win=>13 Zmem=>4
Can anyone shed some light as to how I can go about submitting a binary file via NDM?
Off the cuff...
Try changing RECFM=VB to RECFM=U and specify a BLKSIZE= instead of a LRECL=
This is really not all that different from how executable load modules are stored on the mainframe except you don't want the file to be a PDS dataset. I'm not at my office right now and I think I have some examples of NDM that transmit load modules that I can look-up if this suggestion doesn't work but I think it will.
Give this suggestion a shot and if it still doesn't fly let me know.

Better way to execute remote command on network devices, than expect module

I currently have an implementation using the pexpect python module, which interacts with Juniper, Cisco routers. It spawns a child application and runs command like 'show version' and logs the output.
I am looking for a better way to carry out this process, since if something changes on the switch end (a space or a colon in the prompt after an OS upgrade), then the program will not work. I think Juniper has an API to carry out such operations, but I don't think Cisco has one. I also need to extend this to other switches like HP etc.
Is there a generalized way I can approach this?
I also don't mind writing different code for different devices if required, if a more standard approach than pexpect exists.
Thanks
Using some version of expect is the accepted way of doing this. There's already a mature piece of OSS scripts for doing terminal interaction with most networking devices form most vendors. The same problem exists, but a lot more eyeballs are looking at it and updating things when vendors change prompts.
Check out RANCID.
Here's a quick example of a script I wrote based on RANCID to harvest ACL hit counts on ASAs:
#!/usr/bin/perl
use strict;
use Getopt::Std;
my $usage = "Usage: gethitcnt.pl -c configfile -o outputdir\n\n";
my %opts;
getopts('hc:o:', \%opts);
my $login = sprintf "~%s\/bin\/clogin.in", $ENV{'HOME'};
my $loginrc = sprintf "~%s\/.cloginrc", $ENV{'HOME'};
my $cmdfile = sprintf "~%s\/cmd", $ENV('HOME');
my $date = getdate;
my ($config,$outdir);
unless (-e $login) {
die "Cannot find $login\n\n";
}
unless (-e $loginrc) {
die "Cannot find $loginrc\n\n";
}
if ($opts{h} or !$opts{c}) {
die $usage;
}
if ($opts{o}) {
$outdir = $opts{o};
} else {
$outdir = $ENV{'PWD'};
}
if (-e $opts{c}) {
$config = getconfig($opts{c});
} else {
die "Cannot open config file $opts{c}\n\n";
}
foreach my $firewall (keys %$config) {
foreach my $acl (#{$config->{$firewall}}) {
open (CMD,>$cmdfile);
print CMD "show access-list $acl\n";
print CMD "clear access-list $acl counters\n";
close (CMD);
my $command = ($login,"-x",$cmdfile,$firewall)
open (TMP,"$command |");
my $outfile = sprintf "%s\/%s-%s-%s.txt", $outdir, $firewall, $acl, $date;
open (OUTFILE,>$outfile);
foreach my $line (<TMP>) {
if ($line =~ /\s*(access-list.*\(hitcnt=\d+\))/) {
print OUTFILE "$1\n";
}
}
system ("rm",$cmdfile);
}
}
sub getconfig {
my $configfile = shift;
open(CONFIG,$configfile);
my $out;
foreach (<CONFIG>) {
chomp;
my #$elements = split(/,/);
my $host = shift(#$elements);
$out->{$host} = $elements;
}
close(CONFIG);
return($out);
}
sub getdate {
my #time = localtime;
my #abbr = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
my $month = $abbr[$time[4]];
my $out = sprintf "%s-%d", $month, $time[3];
return($out);
}
In an ideal world, NETCONF would be the solution. It's basically a (set of) wire protocol(s) and some XML encoding for get/set/exec requests against network devices.
See:
RFC 6241
http://datatracker.ietf.org/wg/netconf/charter
http://trac.tools.ietf.org/wg/netconf/trac/wiki
http://www.netconfcentral.org/
Modern versions of JunOS support this, in addition to their older, proprietary interface:
http://www.juniper.net/support/products/junoscript/
Some Cisco hardware/software combinations support it - for example, NETCONF is present in the 12.2(33)SXI and 12.2SY/15.0SY trains on the 6500 sup720/sup2T. I believe all versions of NX-OS (Cisco Nexus) support NETCONF.
I don't know about HP. I do know Extreme XOS supports NETCONF in later versions in addition to Extreme's own XML API.
However - NETCONF is problematic in a few ways:
Although the protocol is standardised, the supported data models aren't. So, you end up with very different XML from the different devices; you'll still need device-specific code. But at least you won't have to screen-scrape and abuse expect, and you'll have much more reliable error detection
Some devices - for example, Cisco IOS - are not really XML under the hood. The XML is generated using a set of rule-based parsers (screen scrapers) and, in my testing, these are often incomplete or buggy. For example, contrary to what Cisco claims, "show run | format" does not "generate XML natively". It turns the Cisco line-based config into XML, and it breaks on a number of config constructs we use (e.g. address-family sub-stanzas of BGP router configs). We ended up not using XML for data and sticking to line-based Cisco commands/config - you still have to parse this, but at least you benefit from the NETCONF command framing and error codes.
Although you can run NETCONF over SSH, many devices still won't perform SSH key-based login (Cisco IOS) meaning you still have to fiddle with hard-coded passwords.

Resources