Unable to get SpamAssassin subject rule to work - spamassassin

I'm trying to catch the hoax domain name invoices I receive for my various websites. These emails have the subject line: [domain] Final Notice. I've added this rule to local.cf (other rules I've added are OK) ---
header LOCAL_DOMAINSCAM Subject =~ /(domain1|domain2|domain3)\.(com|net|org|com\.au) Final Notice/i
score LOCAL_DOMAINSCAM 5
describe LOCAL_DOMAINSCAM Hoax domain name renewal notice
But it's not working. What am I doing wrong?

Have you restarted spamassassin since you added the rule?
service spamassassin restart

Running it through the regex101.com regex tester it looks like you need to remove the \ before the first dot.
header LOCAL_DOMAINSCAM Subject =~ /(domain1|domain2|domain3)\.(com|net|org|com\.au) Final Notice/i
score LOCAL_DOMAINSCAM 5
describe LOCAL_DOMAINSCAM Hoax domain name renewal notice

You need to allow user rules if that's in a personal area; local.cf should contain this line:
allow_user_rules 1
This shouldn't be a problem if your rule definition is itself in SpamAssassin's local.cf and you've restarted the spamd instance you're running (or whatever daemon you're using).
You also should verify that SpamAssassin is loading your rule properly (run spamassassin -D < /path/to/test/message.eml > ~/log 2>&1 and then check your ~/log file to ensure it's loading the rule.

Related

apply recipe to all the servers whose hostnames matches regexp using CHEF

I'm creating a chef recipe to apply a configuration change on all servers whose hostname matches a specific pattern using regexp. However, I'm not sure how to do it.
Example: my hostname looks like this:
dvabwichf01
dvcdwichf01
my recipe in default.rb is :
case node['hostname']
when '*ab*'
template "/tmp/regextest" do
source "test_ab.erb"
mode "0644"
end
else
template "/tmp/regextest" do
source "test_cd.erb"
mode "0644"
end
end
But this is not working as expected, only the "else" template is updating on all servers. please assist.
You would need to use an actual regex, not a string like you have there (also you're using fnmatch glob matching, not a regex). That would only fix when the hostname is literally *ab*. A regexp literal in Ruby usually looks like /whatever/. so when /ab/ in this case.
I used switch for choosing values by adding a method in my helper file (in my case I put it into / app / helpers / application_helper.rb
Example below:
def name_of_your_method(hostname)
case hostname
when "Host1"
"template_1"
when "Host2"
"template_2"
when "Host2"
"template_3"
when "Host3"
"template_4"
else
"template_default"
end
end
Then in your code you would use the name in your method:
<%= user.hostname %>
And in your table(data) you would have a column for hostname(in this example)
Hope this helps

Parslet grammar for rules starting identical

I want to provide a parser for parsing so called Subversion config auth files (see patch based authorization in the Subversion red book). Here I want to define rules for directories like
[/]
* = r
[/trunk]
#PROJECT = rw
So the part of the grammar I have problems is the path definition. I currently have the following rules in Parslet:
rule(:auth_rule_head) { (str('[') >> path >> str(']') >> newline).as(:arh) }
rule(:top) { (str('/')).as(:top) }
rule(:path) { (top | ((str('/') >> path_ele).repeat)).as(:path) }
rule(:path_ele) { ((str('/').absent? >> any).repeat).as(:path_ele) }
So I want to divide in two cases:
To find only [/] (the root directory)
in all other cases [/<dir>] which may be repeated, but has to end without a /
The problematic rule seems to be the path that defines an alternative, here / XOR something like /trunk
I have defined test cases for those, and get the following error when running the test case:
Failed to match sequence (SPACES '[' PATH ']' NEWLINE) at line 1 char 3.
`- Expected "]", but got "t" at line 1 char 3.
So the problem seems to be, that the alternative (rule :path) is chosen all the time top.
What is a solution (as a grammar) for this problem? I think there should be a solution, and this looks like something idiomatic that should happen from here to there. I am not an expert at all with PEG parsers or parser / compiler generation, so if that is a base problem not solvable, I would like to know that as well.
In short: Swap the OR conditions around.
Parlset rules consume the input stream until they get a match, then they stop.
If you have two possible options (an OR), the first is tried, and only if it doesn't match is the second tried.
In your case, as all your paths start with '/' they all match the first part of the path rule, so the second half is never explored.
You need to try to match the full path first, and only match the 'top' if it fails.
# changing this
rule(:path) { (top | ((str('/') >> path_ele).repeat)).as(:path) }
# to this
rule(:path) { ((str('/') >> path_ele).repeat) | top).as(:path) }
# fixes your first problem :)
Also... Be careful of rules that can consume nothing being in a loop.
Repeat by default is repeat(0). Usually it needs to be repeat (1).
rule(:path) { ((str('/') >> path_ele).repeat(1)) | top).as(:path) }
also...
Is "top" really a special case? All paths end in a "/", so top is just the zero length path.
rule(:path) { (path_ele.repeat(0) >> str('/')).as(:path) }
Or
rule(:path) { (str('/') >> path_ele.repeat(0)).as(:path) }
rule(:path_ele) { ((str('/').absent? >> any).repeat(0)).as(:path_ele) >> str('/') }
# assuming "//" is valid otherwise repeat(1)
Seems to be I have not got the problem right. I have tried to reproduce the problem in creating a small example grammar including some unit tests, but now, the thing is working.
If you are interested in it, have a look at the gist https://gist.github.com/mliebelt/a36ace0641e61f49d78f. You should be able to download the file, and run it directly from the command line. You have to have installed first parslet, minitest should be already included in a current Ruby version.
I have added there only the (missing) rule for newline, and added 3 unit tests to test all cases:
The root: /
A path with only one element: /my
A path with more than one element: /my/path
Works like expected, so I get two cases here:
Top element only
One or more path elements
Perhaps this may help others how to debug a situation like that.

How do I disable "TODO" warnings in pylint?

When running pylint on a python file it shows me warnings regarding TODO comments by default. E.g.:
************* Module foo
W:200, 0: TODO(SE): fix this! (fixme)
W:294, 0: TODO(SE): backlog item (fixme)
W:412, 0: TODO(SE): Delete bucket? (fixme)
While I do find this behavior useful, I would like to know of a way of temporarily and/or permanently turn these specific warnings on or off.
I am able to generate a pylint config file:
pylint --generate-rcfile > ~/.pylintrc
I'm just note sure what to put in this file to disable warnings for TODO comments.
in the generated config file, you should see a section
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,XXX,TODO
simply drop TODO from the "notes" list.
The config file is found at
~/.pylintrc
If you have not generated the config file, this can be done with
pylint --generate-rcfile > ~/.pylintrc
Along with the solution posted by #sthenault where you could disable all warnings, Pylint also allows you to ignore a single line (helpful if you would want to deal with it in the future) like so:
A_CONSTANT = 'ugh.' # TODO: update value # pylint: disable=fixme
or by stating the Rule ID:
A_CONSTANT = 'ugh.' # TODO: update value # pylint: disable=W0511
IMHO your code should not have # TODO but during development it might be needed to have TODO for a short period of time and in this case pylint will bother you. To avoid this during this time the best is to globally disable it in the pylintrc by adding fixme to the disable list like this:
[MESSAGES CONTROL]
# globally disable pylint checks (comma separated)
disable=fixme,...
So it let you the time to fix all your TODO and once this is done, you can remove the fixme from the pylintrc. Note if you use an older pylint version you will need to use W0511 instead of fixme. For more detail see https://pylint.pycqa.org/en/stable/technical_reference/features.html#messages-control-options
Changing the pylintrc notes as proposed in the first answer is a bad practice in my opinion. notes is designed to configure wich comments triggers the fixme warning and not designed to disable the warning.
In our projects we have a pylint.cfg file. We use the --rcfile pylint option to point to that file.
In pylint.cfg, I can disable checker W0511, which is the checker that complains about "TODO" and similar terms in comments. Just add W0511 to the comma-separated list for parameter disable.
But remember that, as Uncle Bob Martin says, a TODO is not an excuse to leave bad code in the system, and the code should be scanned regularly to remove TODOs, and pylint and/or sonarqube issues can work as good reminders and motivation for doing so.

Use variables in Autosys in std_out_file

I'd like to set-up dynamic joblog name each time when job run. I'm fine to add timestamp to joblog. Tried to use below:
update_job: ololo_job
std_out_file: >> "%JOBLOG%\ololo_job-%DATE:~0,2%%DATE:~3,2%%DATE:~8,2%-%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%.log"
That doesn't make a trick. Autosys accept the syntax, but then adds "/" before each ":", so Jil starts looking like:
std_out_file: >> "%JOBLOG%\ololo_job-%DATE/:~0,2%%DATE/:~3,2%%DATE/:~8,2%-%TIME/:~0,2%%TIME/:~3,2%%TIME/:~6,2%.log"
and job fails with "Error redirecting output".
I've tried using just:
update_job: ololo_job
std_out_file: >> ololo_job-%DATE%.log
Also no luck, log file had the same name rather then date. Had anyone deal with that?
So:
We can do it in Unix/Linux systems
We can't do it Windows: we can have date, but we can't have time, so for the jobs that run more than 1 time per day, we can "do it like they do it on discovery channel"
%JOBLOG%/%AUTO_JOB_NAME%.%AUTORUNID%.log
%AUTO_JOB_NAME%.%AUTORUN% will have a unique id generated

Ruby : Use external script from within a script to do a comparison

So I got a script (A) that finds a suitable IP address for a new virtual server. At first, it takes a look in the database to see if the first ip he chose isn't already taken by another server. If the IP is not already in use, the script pings it. If there is no response from the ping, then we get to the next step and this is where I'm having a problem.
In the next step, I have to check if the IP address is already registred in the netscaler (router) or not. To do this, I must use another script on the same machine (B). This other script return the list of all the ips defined in the netscaler. When I run it, the output looks like this
x.x.x.x
x.x.x.x
x.x.x.x (and so on..).
I found many ways to execute the script B from whiting the script A, but none of what I found allow me to do what I'd like to.
My goal is to compare the ip my script found with all of those that are listed, without having those last ones printed on the screen.
So, to make it a bit clearer, let's say that the scrip A found the IP : 1.2.3.4
It would then call script B that would return to script A this list
1.2.3.5
1.2.4.5
1.2.5.1
and so on.
and then A would compare 1.2.3.4 with all those returned by script B without actually showing them on screen.
Thank you very much!
I would separate scriptB business logic from scriptB ui (CLI) logic:
scriptA.rb
scriptB.rb
netscaler.rb # extract logic here
Extract your list of all the ips defined in the netscaler logic into separate class/method:
#netscaler.rb
class Netscaler
def self.list_ips
# return array of ips here
end
end
#scriptB.rb
require_relative 'netscaler'
ips = Netscaler.list_ips
puts ips # script B may show these ips on the screen
...
#scriptA.rb
require_relative 'netscaler'
ips = Netscaler.list_ips
# script A will not show them. Instead it will operate on the returned result.
...
You can use backticks to execute script B and return the output:
ip_list = `scriptB`.split("\n")
This can be plugged into Alex's organizational suggestion. I would do this if script B is a non-Ruby script that you don't control.
Note that if there is any leading or trailing whitespace you can add a .map(&:strip) to the end.

Resources