Algorithm-ToNumberMunger

 view release on metacpan or  search on metacpan

lib/Algorithm/ToNumberMunger.pm  view on Meta::CPAN


If you would rather the number carry B<no> implied gradient, see
L</sasl_mech_iana_enum>, which numbers the same set alphabetically.

=head2 sasl_mech_iana_enum

    { munger => 'sasl_mech_iana_enum', default => -1 }

The nominal counterpart of L</sasl_mech_enum>: the B<same> set of SASL
mechanisms (the two share one list, so they can never cover different
mechanisms), but numbered B<alphabetically> rather than by strength -- a
purely categorical encoding for when a strength gradient would be a
misleading feature. Lookup rules and the no-numeric-passthrough behaviour are
as L</sasl_mech_enum>.

=head2 http_version_enum

    { munger => 'http_version_enum', default => -1 }

Named-map enum (lookup rules as L</dns_rcode_enum>) mapping the HTTP protocol
version to an B<ordinal>: C<HTTP/0.9> 0, C<HTTP/1.0> 1, C<HTTP/1.1> 2,
C<HTTP/2.0> 3, C<HTTP/3.0> 4. The access-log spelling (C<HTTP/1.1>), the bare
number (C<1.1>), and the ALPN/shorthand forms (C<h2>, C<h2c>, C<h3>) are all
accepted, so an Apache/nginx C<%H> field and a Suricata C<http.protocol> land
in one column. Ordinal so "older than expected" (a C<0.9>/C<1.0> request from
a scanner) is a monotone feature a threshold split can express. Because these
are ordinals of our own numbering -- and a logged C<2> denotes version C<2.0>,
not the integer two -- numeric inputs are B<not> passed through.

=head2 spamassassin_autolearn_enum

    { munger => 'spamassassin_autolearn_enum', default => -1 }

Named-map enum (lookup rules as L</dns_rcode_enum>) for SpamAssassin's
C<autolearn=> field: C<no> 0, C<ham> 1, C<spam> 2, C<disabled> 3, C<failed> 4,
C<unavailable> 5, C<unknown> 6. The numbering is essentially nominal (the
Bayes auto-learn outcome is a category, not a scale), arranged only so the
"nothing was learned" states cluster away from the ham/spam ones. The spam
I<score> is already a number for L</num>, and the spam/ham verdict a L</bool>;
this covers the one autolearn field neither derives. Numeric inputs are not
passed through.

=head2 rspamd_action_enum

    { munger => 'rspamd_action_enum', default => -1 }

Named-map enum (lookup rules as L</dns_rcode_enum>) for rspamd's action,
numbered by B<increasing severity> so the ordinal is a usable feature on its
own: C<no action> 0, C<greylist> 1, C<add header> 2, C<rewrite subject> 3,
C<soft reject> 4, C<reject> 5. Both the space and underscore spellings rspamd
emits (C<no action>/C<no_action>, C<add header>/C<add_header>, ...) are
accepted. Numeric inputs are not passed through.

=head2 ssh_auth_method_enum

    { munger => 'ssh_auth_method_enum', default => -1 }

Named-map enum (lookup rules as L</dns_rcode_enum>) for the OpenSSH
authentication method logged by C<sshd> (the word after C<Accepted>/C<Failed>,
or the C<method=> field): C<none> 0, C<password> 1, C<keyboard-interactive> 2,
C<hostbased> 3, C<publickey> 4, C<gssapi-with-mic> 5, C<gssapi-keyex> 6, with
bare C<gssapi> aliased to C<gssapi-with-mic>. Numbered roughly
B<weakest-to-strongest> so "weaker credential than expected" is a monotone
feature; the ordering is a judgement call, not a registry. Numeric inputs are
not passed through.

=head2 amavis_category_enum

    { munger => 'amavis_category_enum', default => -1 }

Named-map enum (lookup rules as L</dns_rcode_enum>) for the amavisd-new
content category, ordered clean-to-worst: C<clean> 0, C<oversized> 1,
C<unchecked> 2, C<spammy> 3, C<spam> 4, C<badheader> 5, C<banned> 6,
C<infected> 7, C<mtablocked> 8. The hyphenated spellings (C<bad-header>,
C<mta-blocked>) and the legacy C<virus> (for C<infected>) are accepted as
aliases. The Passed/Blocked I<action> itself is a L</bool>; this is the
finer-grained reason. Numeric inputs are not passed through.

=head2 systemd_result_enum

    { munger => 'systemd_result_enum', default => -1 }

Named-map enum (lookup rules as L</dns_rcode_enum>) for a systemd unit
C<result> (as in C<Failed with result 'timeout'>): C<success> 0, C<protocol>
1, C<timeout> 2, C<exit-code> 3, C<signal> 4, C<core-dump> 5, C<watchdog> 6,
C<start-limit-hit> 7, C<oom-kill> 8, C<resources> 9. The underscore spellings
(C<exit_code>, C<core_dump>, C<start_limit_hit>, C<oom_kill>) are accepted as
aliases. Numeric inputs are not passed through.

=head2 clamav_result_enum

    { munger => 'clamav_result_enum', default => -1 }

Named-map enum (lookup rules as L</dns_rcode_enum>) for a ClamAV per-target
verdict as logged by C<clamd> / clamav-milter: C<OK> 0, C<FOUND> 1, C<ERROR>
2. Small but exactly the signal worth flagging (a C<FOUND> line). Numeric
inputs are not passed through.

=head2 kerberos_etype_enum

    { munger => 'kerberos_etype_enum', default => -1 }

Named-map enum for the Kerberos ticket encryption type -- Windows events
4768/4769 (logged as hex, C<0x17>) and any other AD/Kerberos source. The
values are the RFC 3961 etype numbers, which B<are> the wire encoding, so
(unlike most of the enums here) a decimal input passes through unchanged: the
map exists only to resolve the hex spellings (C<0x17> => 23, C<0x12> => 18,
...) and the RFC/MIT names (C<rc4-hmac>/C<rc4>/C<arcfour-hmac> => 23,
C<aes256-cts-hmac-sha1-96>/C<aes256> => 18, C<aes128> => 17, C<des3> => 16,
C<des-cbc-md5> => 3, C<des-cbc-crc> => 1) onto that same number. The classic
use is flagging C<rc4-hmac> (0x17) as a downgrade/roasting signal against an
C<aes256> baseline. Lookup is case-insensitive; an unlisted etype croaks
unless a numeric C<default> is given.

=head2 windows_integrity_level_enum

    { munger => 'windows_integrity_level_enum', default => -1 }

Named-map enum (lookup rules as L</dns_rcode_enum>) for the Windows / Sysmon
process integrity level, as an B<ordinal>: C<untrusted> 0, C<low> 1, C<medium>
2, C<high> 3, C<system> 4 (with C<mediumplus> folded into C<medium>). The

lib/Algorithm/ToNumberMunger.pm  view on Meta::CPAN

					'http/0.9' => 0,
					'http/1.0' => 1,
					'http/1.1' => 2,
					'http/2.0' => 3,
					'http/3.0' => 4,
				);
				$v{'0.9'} = 0;
				$v{'1.0'} = 1;
				$v{'1.1'} = 2;
				$v{'2.0'} = $v{'2'} = $v{'http/2'} = $v{'h2'} = $v{'h2c'} = 3;
				$v{'3.0'} = $v{'3'} = $v{'http/3'} = $v{'h3'} = 4;
				%v;
			},
		},
	},
	spamassassin_autolearn => {
		numeric => 0,
		map     => {
			# SpamAssassin's autolearn= field. Nominal, but ordered so
			# "no learning happened" sorts below the ham/spam outcomes.
			no          => 0,
			ham         => 1,
			spam        => 2,
			disabled    => 3,
			failed      => 4,
			unavailable => 5,
			unknown     => 6,
		},
	},
	rspamd_action => {
		numeric => 0,
		map     => {
			# rspamd's action, ordered by severity. Accept both the space
			# and underscore spellings rspamd emits across its outputs.
			do {
				my %a = (
					'no action'       => 0,
					'greylist'        => 1,
					'add header'      => 2,
					'rewrite subject' => 3,
					'soft reject'     => 4,
					'reject'          => 5,
				);
				$a{'no_action'}       = $a{'noaction'} = 0;
				$a{'add_header'}      = 2;
				$a{'rewrite_subject'} = 3;
				$a{'soft_reject'}     = $a{'soft-reject'} = 4;
				%a;
			},
		},
	},
	ssh_auth_method => {
		numeric => 0,
		map     => {
			# OpenSSH authentication method, ordered by credential strength
			# (weakest first) so "weaker than expected" is monotone. The
			# ordering is a judgement call, not an IANA registry.
			do {
				my @o = qw(
					none password keyboard-interactive
					hostbased publickey
					gssapi-with-mic gssapi-keyex
				);
				my %m = map { $o[$_] => $_ } 0 .. $#o;
				$m{'gssapi'} = $m{'gssapi-with-mic'};
				%m;
			},
		},
	},
	amavis_category => {
		numeric => 0,
		map     => {
			# amavisd-new content category, ordered clean -> worst.
			do {
				my @o = qw(
					clean oversized unchecked spammy spam
					badheader banned infected mtablocked
				);
				my %m = map { $o[$_] => $_ } 0 .. $#o;
				$m{'bad-header'}  = $m{'badheader'};
				$m{'virus'}       = $m{'infected'};
				$m{'mta-blocked'} = $m{'mtablocked'};
				%m;
			},
		},
	},
	systemd_result => {
		numeric => 0,
		map     => {
			# systemd unit "result" (e.g. "Failed with result 'timeout'").
			do {
				my @o = qw(
					success protocol timeout exit-code signal
					core-dump watchdog start-limit-hit oom-kill resources
				);
				my %m = map { $o[$_] => $_ } 0 .. $#o;
				$m{'exit_code'}       = $m{'exit-code'};
				$m{'core_dump'}       = $m{'core-dump'};
				$m{'start_limit_hit'} = $m{'start-limit-hit'};
				$m{'oom_kill'}        = $m{'oom-kill'};
				%m;
			},
		},
	},
	clamav_result => {
		numeric => 0,
		map     => {
			# clamd / clamav-milter per-target verdict.
			ok    => 0,
			found => 1,
			error => 2,
		},
	},
	kerberos_etype => {
		numeric => 1,    # RFC 3961 etype numbers are the wire value; a logged 23 IS rc4
		map     => {
			# Windows logs the ticket encryption type as hex ("0x17"); the
			# RFC/MIT names appear in other Kerberos logs. Everything resolves
			# to the decimal etype number, so a decimal input passes through.
			do {
				my %e = (



( run in 0.515 second using v1.01-cache-2.11-cpan-bbcb1afb8fc )