Closed dfch closed 9 years ago
Hi.
Thank you so much for sending through the issue! It has made me very excited that someone has even looked at using my code! You really made my weekend!
Unfortunately my timestamp seems to be a broken attempt at SYSLOG rfc3164. It seems my code is not compliant correctly to either RFC.
Whilst the modification of the timestamp might make the code compliant in terms of the time format, it introduces some other issues, which can be easily fixed.
I am working on an RFC 5424 compliant update now, which will include your updates, as well as a little extra to push it to full compliance.
I was using your module to test the Syslog UDP input adapter of Graylog2 (which seems to be rather RFC5424 compliant). If you are updating the code anyway, you could also implement a switch/option to choose between the datetime and general format of the message and implement support for different RFCs (as this is a common case of error when processing Syslog). And yes, I was glad to be able to use your script, so I would not have to write one myself. Always good to be able to reuse existing code...
Just reading https://tools.ietf.org/html/rfc5424
Section 6 outlines the message layout as something like:
$FullSyslogMessage = "<{0}>1 {1} {2} - - - - {3}" -f $Priority, $Timestamp.ToString('yyyy-MM-ddTHH:mm:ss.ffffffzzz'), $Hostname, $Message
The thing missing from your orginial code is the version number, which I believe is 1 for RFC 5424, and the new fields introduced for Application Name, Process ID, Message ID and structured data.
I am creating a quick fork for testing, will let you know the details in a second.
Please take a look at https://github.com/kjacobsen/PowerShellSyslog/blob/RFC5424/Functions/send-syslog.ps1
Should be sending this message
<33>1 2015-01-12T00:34:47.399567+11:00 server.domain - - - - This is a test message
RFC description is a bit tricky, as it says VERSION = NONZERO-DIGIT 0*2DIGIT
, which would mean that you MAY use a version field, but do not have to (as it says 0*2
, meaning 0, 1 or 2 digits). See 3.6. Variable Repetition: *Rule in RFC5234 for the ABNF format. But you are certainly right, that it seems to be a good idea to include a 1
as a version number (as described in 9.1. VERSION).
So I downloaded a few syslog servers (for Windows). I notice that InterActive Syslog appears to expect the version.
Not quite sure if you read my comment on your commit 4d9c0fd. For me it looks you can close the issue after merging the branch/commit.
I have merged the branch back in to master, added the paameters and performed some cleanup. One thing to note is the hostname is now RFC compliant as well (to an extent). It will use FQDN - Static IP - Hostname in that order if the hostname is not specified.
I worked out how I went wrong with this, I used Wikipedia for the message format specification. https://en.wikipedia.org/wiki/Syslog
yep, you are right, it shows quite an abstracted view of the actual protocol ...
I checked your code and saw that you now also have the $ApplicationName as a default input parameter. Instead of hard coding 'powershell.exe' you could use something like $Host.Name (which wold resolve to ConsoleHost or NuGet or wherever you use it) or better $MyInvocation.Parent. ... to get the caller's function name. I just mention this as the PowerShell executable itself does not really tell you much, but the caller of your function may. But this is really cosmetic (as I do not really like hard coded constants...). Again thanks for taking your time to update your code! I will now continue to use it for my Graylog tests.
The Cmdlet send-syslog.ps1 states in its description to send a syslog message as defined in RFC 5424. However the generated timestamp in the Cmdlet incorrectly formats a timestamp when none is specified by the caller, nor does it validate or convert the timestamp if specified by the caller.
As defined in 6.2.3. TIMESTAMP the timestamp MUST include a
(space) (separating the timezone with a space will result in the timezone to be treated as the 6.2.4. HOSTNAME of the message).
T
(capital T) delimiter and MUST use-
(dash) for date separation. Furthermore, the time portion of the timestamp MUST NOT be prefixed with a-
(dash) and the UTC offset MUST NOT be separated by aWhen invoking the following command:
Send-SyslogMessage -Server 192.168.174.161 -Message tralala -Severity Emergency -Facility local0 -UDPPort 49153 -Hostname s000000.dfch.biz
... the resulting payload (captured with Wireshark) looks like this:
<128>2015:01:11:-09:03:24 +01:00 s000000.dfch.biz tralala
... instead the timestamp MUST look like this:
<128>2015-01-11T09:03:24+01:00 s000000.dfch.biz tralala
Recommended code change for timestamp generation: Instead of:
... it should be generated like this:
Furthermore, it is recommended to change the parameter $Timestamp to a DateTime or DateTimeOffset data type, to be able to easier enforce correct dates, by converting them into a correct formt like this:
Note: always specifying the fraction of a second (see A.4. TIME-SECFRAC Precision) will ensure the highest resolution possible, so the complete section could be rewritten like this: