Technitium parser

Hi, I'm trying to write a custom parser for technitium failed auth logs. However I'm unable to get it working properly... (Grok Debugger confirms that the correct things are getting matched though)
name: PintjesB/technitium-logs
description: "Parse Technitium auth logs"
onsuccess: next_stage
pattern_syntax:
DATETIME_CUSTOM: '%{YEAR:year}-%{MONTHNUM:month}-%{MONTHDAY:day} %{TIME:time} %{TZ}'
nodes:
- grok:
pattern: '^\[%{DATETIME_CUSTOM}\] \[%{IP:source_ip}:%{INT:source_port}\] DnsServerCore.DnsWebServiceException: Invalid username or password for user: %{USERNAME:username}'
apply_on: message
statics:
- meta: log_type
value: technitium_failed_auth

statics:
- meta: service
value: technitium
- target: evt.StrTime
expression: "evt.Parsed.day + '/' + evt.Parsed.month + '/' + evt.Parsed.year + ' ' + evt.Parsed.time"
- meta: source_ip
expression: "evt.Parsed.source_ip"
- meta: source_port
expression: "evt.Parsed.source_port"
- meta: username
expression: "evt.Parsed.username"
name: PintjesB/technitium-logs
description: "Parse Technitium auth logs"
onsuccess: next_stage
pattern_syntax:
DATETIME_CUSTOM: '%{YEAR:year}-%{MONTHNUM:month}-%{MONTHDAY:day} %{TIME:time} %{TZ}'
nodes:
- grok:
pattern: '^\[%{DATETIME_CUSTOM}\] \[%{IP:source_ip}:%{INT:source_port}\] DnsServerCore.DnsWebServiceException: Invalid username or password for user: %{USERNAME:username}'
apply_on: message
statics:
- meta: log_type
value: technitium_failed_auth

statics:
- meta: service
value: technitium
- target: evt.StrTime
expression: "evt.Parsed.day + '/' + evt.Parsed.month + '/' + evt.Parsed.year + ' ' + evt.Parsed.time"
- meta: source_ip
expression: "evt.Parsed.source_ip"
- meta: source_port
expression: "evt.Parsed.source_port"
- meta: username
expression: "evt.Parsed.username"
Log example:
[2025-07-28 05:34:01 UTC] [169.254.44.3:50051] DnsServerCore.DnsWebServiceException: Invalid username or password for user: admin
[2025-07-28 05:34:01 UTC] [169.254.44.3:50051] DnsServerCore.DnsWebServiceException: Invalid username or password for user: admin
However, I keep getting this log:
╰─✗ csdev hubtest run technitium-logs
Running test 'technitium-logs'
WARNING Line 0/1 is missing evt.StrTime. It is most likely a mistake as it will prevent your logs to be processed in time-machine/forensic mode. file=/home/ubuntu/crowdsec-v1.6.8/tests/hub/.tests/technitium-logs/results/parser-dump.yaml
WARNING Assert file '/home/ubuntu/crowdsec-v1.6.8/tests/hub/.tests/technitium-logs/parser.assert' is empty, generating assertion:

len(results) == 2
len(results["s01-parse"]["PintjesB/technitium-logs"]) == 1
results["s01-parse"]["PintjesB/technitium-logs"][0].Success == false
len(results["success"][""]) == 0

Error: please fill your assert file(s) for test 'technitium-logs', exiting
╰─✗ csdev hubtest run technitium-logs
Running test 'technitium-logs'
WARNING Line 0/1 is missing evt.StrTime. It is most likely a mistake as it will prevent your logs to be processed in time-machine/forensic mode. file=/home/ubuntu/crowdsec-v1.6.8/tests/hub/.tests/technitium-logs/results/parser-dump.yaml
WARNING Assert file '/home/ubuntu/crowdsec-v1.6.8/tests/hub/.tests/technitium-logs/parser.assert' is empty, generating assertion:

len(results) == 2
len(results["s01-parse"]["PintjesB/technitium-logs"]) == 1
results["s01-parse"]["PintjesB/technitium-logs"][0].Success == false
len(results["success"][""]) == 0

Error: please fill your assert file(s) for test 'technitium-logs', exiting
8 Replies
CrowdSec
CrowdSec5w ago
Important Information
This post has been marked as resolved. If this is a mistake please press the red button below or type /unresolve
© Created By WhyAydan for CrowdSec ❤️
iiamloz
iiamloz5w ago
Seems your hubtest may be missing the s00 parser crowdsecurity/syslog-logs
PintjesBier
PintjesBierOP5w ago
I can see the syslog-logs s00 parser in it's s00 folder, if that's what you're referring to However, I don't think this uses syslog format?
iiamloz
iiamloz5w ago
No I mean within your tests you define you need to add crowdsecurity/syslog-logs, nope but this parser has the "catch all" for file definitions also there is no filter property you should add a filter: evt.Parsed.program == 'technitium' for example the evt.Parsed.program gets set from crowdsecurity/syslog-logs using the labels.type
PintjesBier
PintjesBierOP5w ago
That seems to have done the trick! Can you elaborate on why syslog s00 parsing is needed even when it's not in syslog format?
iiamloz
iiamloz5w ago
at the bottom of the parser is a catch all style filter which sets the evt.Parsed.program property and moves it to s01 stage, then in s01 we need to use the filter property to make sure we only attempt to parse the lines that are appropiate for this parser. snippet for syslog-logs:
---
#if it's not syslog, the type is the progname
filter: "evt.Line.Labels.type not in ['syslog', 'unifi']"
onsuccess: next_stage
name: crowdsecurity/non-syslog
#debug: true
statics:
- parsed: message
expression: evt.Line.Raw
- parsed: program
expression: evt.Line.Labels.type
- meta: datasource_path
expression: evt.Line.Src
- meta: datasource_type
expression: evt.Line.Module
---
#if it's not syslog, the type is the progname
filter: "evt.Line.Labels.type not in ['syslog', 'unifi']"
onsuccess: next_stage
name: crowdsecurity/non-syslog
#debug: true
statics:
- parsed: message
expression: evt.Line.Raw
- parsed: program
expression: evt.Line.Labels.type
- meta: datasource_path
expression: evt.Line.Src
- meta: datasource_type
expression: evt.Line.Module
PintjesBier
PintjesBierOP5w ago
I seeee. Alright Thanks
CrowdSec
CrowdSec5w ago
Resolving Technitium parser This has now been resolved. If you think this is a mistake please run /unresolve

Did you find this page helpful?