Friday, October 8, 2010

Oracle vs. Community

Since Oracle bought Sun Microsystems a while ago, I follow what happens to Java, Openoffice and the community process.

All I can say so far is, that in my opinion Oracle made a very bad job. Instead of holding the community together to keep the momentum and to build a big force against M$, they disappointed many people.
All you can see is forks everywhere. OpenOffice forked to LibraOffice, OpenJDK currently seem to go different ways than the community, MySQL forked into several independent projects and OpenSolaris (not open anymore) forked also.

So the big question is: What the heck is the plan of Oracle? Do they have any?

Thursday, July 1, 2010

Setting udev permission in CentOS5 for Bacula

If you use Bacula and wonder why your changer device (/dev/sgX) has wrong permissions, you must understand that udev is responsible on RedHat/Fedora for setting up the device nodes in /dev.

To change the group and permission of your changer device, add a script which sets the group and permission for your changer device.

Example for /dev/sg1:

vi /etc/udev/rules.d/55-bacula.rules


# fix the permissions of the standard devices to group "disk" (which bacula is a
 member of)
KERNEL=="sg[0-9]*", BUS=="scsi", MODE="0660", GROUP="disk"


Then reboot your server.

After reboot, you see the changed group on the sg devices:


# ls -al /dev/sg*
crw-rw---- 1 root disk 21, 0 Sep  8 14:42 /dev/sg0
crw-rw---- 1 root disk 21, 1 Sep  8 14:42 /dev/sg1
crw-rw---- 1 root disk 21, 2 Sep  8 14:42 /dev/sg2
crw-rw---- 1 root disk 21, 3 Sep  8 14:42 /dev/sg3
crw-rw---- 1 root disk 21, 4 Sep  8 14:42 /dev/sg4
crw-rw---- 1 root disk 21, 5 Sep  8 14:42 /dev/sg5
crw-rw---- 1 root disk 21, 6 Sep  8 14:42 /dev/sg6

Friday, June 18, 2010

Using Spring-Security Database in Spring-Roo

Spring Roo is an excellent rapid development tool for Spring Framework based applications.
The current Spring Roo (1.1.0.M1) Security support is very basic and does not support databases out-of-the-box.
To integrate Spring Security with a database backed user and authorization storage, you currently need to set it up yourself.

For this to work, it is required that you already configured your persistence layer in Roo.

Step1: Add the Entities for Spring-Security
Note that in my approach, I avoid reserved SQL keywords for tables and columns.
Roo statements:

// domain.Roles (Spring Security Authorities)
entity --class ~.domain.Roles --testAutomatically
field string --fieldName nameDa --notNull --sizeMax 50 --class ~.domain.Roles

// domain.Users
entity --class ~.domain.Users --testAutomatically
field string --fieldName usernameDa --notNull --sizeMin 3 --sizeMax 30
field string --fieldName passwordDa --sizeMax 100
field boolean --fieldName enabledDa --notNull true
field set --fieldName roles --type ~.domain.Roles --cardinality MANY_TO_MANY --class ~.domain.Users

Step2: Create Web Tier Controllers (to manage roles and users)
controller scaffold --entity ~.domain.Users --class ~.web.UsersController
controller scaffold --entity ~.domain.Roles --class ~.web.RolesController

Step3: Setup security in Roo
Within the roo shell, type "security setup". This creates the security config file and adds needed dependencies to the main pom.xml file.

Step4: Configure Spring Security
File: applicationContext-security
Replace the authentication-manager with a dao based one.
Note the queries to check the user and to get the Authorities which reflects the non-standard table and column names:

<!-- Configure Authentication mechanism -->
<authentication-manager alias="authenticationManager">
<!-- DAO Based Security -->
<authentication-provider>
<password-encoder hash="md5"/>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="SELECT U.username_da AS username, U.password_da as password, U.enabled_da as enabled FROM users U where U.username_da=?"
authorities-by-username-query="SELECT U.username_da as username, A.name_da as authority FROM users U left join users_roles UA on U.id=UA.users left join roles A on UA.roles = A.id WHERE U.username_da=?" />
</authentication-provider>
</authentication-manager>

<!-- Security event logging -->
<beans:bean id="loggerListener"
class="org.springframework.security.authentication.event.LoggerListener" />


Step5: Initial Users and Roles
I recommend to start the application now, create your needed roles (e.g. "ROLE_ADMIN", "ROLE_SUPERVISOR") and at least an admin user with ROLE_ADMIN and ROLE_SUPERVISOR assigned. Afterwards secure the roles and users resources in the applicationContext-security.xml (so that only admins can access these controllers):

<intercept-url pattern="/users**" access="hasRole('ROLE_ADMIN')"/>

<intercept-url pattern="/roles**" access="hasRole('ROLE_ADMIN')"/>

Saturday, March 27, 2010

Train Snow Leopard Spamassassin using shared IMAP folders

By default, Apple only supports training the Spamassassin bayesian spam filter for spam/ham by using two special useraccounts "junkmail" and "notjunkmail".
This might work for you.

But I for example use a shared imap account as a public folder for people in the company to share common emails.
The other day, I thought of a possibility to add two folders to this shared account (for SPAM/HAM emails) to learn spamassassin from these folders.
It works.
The only thing you need is:
  • Folders in a shared IMAP account for spam and ham emails (e.g. "SPAM_not_detected" and "SPAM_false_positive")
  • A script which learns from these emails and deletes them afterwards.
  • A launcher script and a plist file for it to start regularly.
Here it comes.
Save the following file to /usr/local/bin/train-spamassassin:

#!/bin/sh
# Script to Train Spamassassin SPAM/HAM emails in certain folders
# USE AT YOUR OWN RISK!

################################################################################
# SETUP
# Set to mail user which hold the spam/ham folders
MAIL_USER=exampleuser
# Folder for not detected Spams (relative)
SPAM_MAILDIR="SPAM_not_detected"
# Folder for not false positive copies (relative)
FALSE_POSITIVE_MAILDIR="SPAM_false_positive"
# Email address to send status email to. You need to enable mail sending below.
EMAILADDR=you@anything.xxxx
################################################################################
SA_LEARN_PATH=/usr/bin/sa-learn
DB_PATH=/var/amavis/.spamassassin
SA_LEARN_CMD="$SA_LEARN_PATH --dbpath $DB_PATH --no-sync"

# Remove remark from next line and the last line in script to enable email sending of status
#(
echo "################################################################"
echo "Spam Assassin Training Script $0"
echo "################################################################"
# determine users GUID
USER_GUID=`/usr/bin/cvt_mail_data -i "$MAIL_USER"`
if [ `expr "$USER_GUID" : '[0-9A-F]*-[0-9A-F]*-[0-9A-F]*-[0-9A-F]*-[0-9A-F]*'` -eq 0 ]
then
echo "Error: Can't find GUID of mail user $MAIL_USER"
echo $USER_GUID
exit 1
fi
# determine the mail store path
PART_MAP_PATH=/etc/dovecot/partition_map.conf
MAIL_STORE_PATH=`grep "^default:" $PART_MAP_PATH | sed s,default:,,`
case "$MAIL_STORE_PATH" in
/*) # OK
;;
*) echo "Can't determine mail store path from $PART_MAP_PATH"
exit 1
;;
esac
USER_MAIL_PATH="$MAIL_STORE_PATH/$USER_GUID"
SPAM_MAIL_PATH=$USER_MAIL_PATH/.$SPAM_MAILDIR
FALSE_POSITIVE_MAIL_PATH=$USER_MAIL_PATH/.$FALSE_POSITIVE_MAILDIR

if [ ! -d $SPAM_MAIL_PATH ]; then
echo "Error: Spam mail dir $SPAM_MAIL_PATH does not exist"
exit 1
fi
if [ ! -d $FALSE_POSITIVE_MAIL_PATH ]; then
echo "Error: False postives mail dir $FALSE_POSITIVE_MAIL_PATH does not exist"
exit 1
fi

echo " "
echo "################################################################"
echo "Learning SPAM Entries in $SPAM_MAIL_PATH"
echo "################################################################"

$SA_LEARN_CMD --spam $SPAM_MAIL_PATH/cur/
$SA_LEARN_CMD --spam $SPAM_MAIL_PATH/new/
count=`ls $SPAM_MAIL_PATH/cur/ | wc -l`
echo "There are $count mails in the folder"
if [ $count != 0 ]; then
echo "Deleting spam mails.."
find $SPAM_MAIL_PATH/cur/ -type f -print0 | xargs -0 rm
else
echo "No Mails to delete."
fi

################################################################################
# FALSE Positives
################################################################################
echo " "
echo "##########################################################"
echo "Learning False Positive Entries in $FALSE_POSITIVE_MAIL_PATH"
echo "###########################################################"
$SA_LEARN_CMD --ham $FALSE_POSITIVE_MAIL_PATH/cur/
$SA_LEARN_CMD --ham $FALSE_POSITIVE_MAIL_PATH/tmp/

count=`ls $FALSE_POSITIVE_MAIL_PATH/cur/ | wc -l`
if [ $count != 0 ]; then
echo "Deleting false positives.."
find $FALSE_POSITIVE_MAIL_PATH/cur/ -type f -print0 | xargs -0 rm
else
echo "No mails to delete."
fi

echo "syncing database.."
sudo $SA_LEARN_PATH --dbpath $DB_PATH --sync

echo "end of script."
##) | /usr/bin/mail -s "$HOSTNAME Spamassassin Training status" $EMAILADDR


Save this script as /usr/local/bin/train-spamassassin-runner:
#!/bin/sh
# run train-spamassassin. Needed for launchd
/usr/local/bin/train-spamassassin
stat=$?
if [ $stat = 0 ]; then
# everything is ok
syslog -s -l NOTICE "$0: train-spamassassin signaled success"
exit 0
else
syslog -s -l NOTICE "$0: train-spamassassin signaled error $stat"
exit $stat
fi


And of course a launchd plist file to start the script regularly.
Save this content to /Library/LaunchDaemons/org.roosbertl.spamassassinlearn.plist:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0">
<!-- Start spamassassin sa-learn script every day at 6:33
24/03/10 Atomic.
-->
<dict>
<key>Label</key>
<string>org.roosbertl.spamassassinlearn</string>
<key>UserName</key>
<string>root</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/train-spamassassin-runner</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StartCalendarInterval</key>
<array>
<dict>
<key>Hour</key>
<integer>6</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>12</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>18</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
</array>
</dict>
</plist>

Then activate the start of the script:

sudo launchctl load /Library/LaunchDaemons/org.roosbertl.spamassassinlearn.plist

Now your users just have to move spam/ham email to the corresponding shared imap folders.

Friday, January 8, 2010

Using SquirrelMail or RoundCube server side rules on Snow Leopard Server

Apple Snow Leopard Server comes with a very limited Mail Sieve rule management within the wiki application.
If you are disappointed by Snow Leopard Servers cappabilities to manage sieve rules (Server Side Mail Rules), there are solutions available.

Prerequisites
Enable Server Side Rules in Mail Server
Start Server Admin
Mail > Settings > Advanced: Tick "PLAIN" on IMAP/POP and save it
Mail > Settings > Filters: Tick "Enable Server Side mail rules", save it and restart the mail service.

Squirrelmail
SquirrelMail is the default webmailer in SLS. You can use the plugin avelsieve to manage server side mail rules. Download avelsieve (I recommend version 1.9.9) and unpack in directory /usr/share/squirrelmail/plugins (so that directory avelsieve is within the plugins dir).
Note that you also need to download javascript_libs plugin, if you use a recent version (>=1.9.8) of avelsieve.
If you need the javascript_libs plugin, also unpack it in squirrelmail's plugins dir.

Then edit the file plugins/avelsieve/config/config.php (copy config_sample.php to config.php if not exisiting).
Change the authentication mechanism to:
$sieve_preferred_sasl_mech = 'PLAIN';

Edit file /usr/share/squirrelmail/config/config.php and register the plugin(s):
$plugins[0] = 'avelsieve';
$plugins[1] = 'javascript_libs'; // only if using a newer version of avelsieve. See avelsieve page

Access the Webmailer (http://<SLS_server_name>/webmail/ and check the filter connection.

Roundcube
Sorrily Apple decided to use the old-fashioned, ugly SquirrelMail webmailer and not RoundCube.
RoundCube is much nicer and also the "managesieve" plugin available for it is much better than avelsieve in SquirrelMail.
Luckily you can install RoundCube on your SLS without harming the default installation.
To install RoundCube on SLS, see here

Enable managesieve plugin
ManageSieve plugin comes with RoundCube.
To enable it, edit file roundcube/config/main.inc.php:
$rcmail_config['plugins'] = array('managesieve');

Then edit file plugins/managesieve/lib/Net/Sieve.php:
- comment line var $supportedAuthMethods=.... (comment with //)
- uncomment line var $supportedAuthMethods=array( 'PLAIN' , 'Login' );

Set timezone
You will get timezone errors in the roundcube/logs/errors log file.
To fix this, add the following to
/etc/php.ini:
enable and change date.timezone to a value you find in the php doc
Example:
date.timezone = Europe/Berlin

Test roundcube
Now test roundcube by accessing http://<SLS_server_name>/roundcube/
Login as a user you like to change server side rules for
Click on "Settings" in the upper right corner, then on Filter.
If you see the page and no error occurs, you are sucessfully connected to the sieve backend of IMAP!
You now can create your rules.

The Sieve configuration file
The sieve config file is stored in dir
/private/var/spool/imap/dovecot/sieve-scripts/<GUID_OF_USER>/

The good thing is, that every rule managing application (Apple web rule management, SquirrelMail, RoundCube) you use, store its own file. So one app is not overwriting the others config file.
This is of importance if you enable the apple built-in crippled rule management and store the rules, there. This creates an own file "wiki_server_rules.sieve" in your sieve script dir and enables it by the link dovecot.sieve -> wiki_server_rules.sieve

To re-enable your SquirrelMail/RoundCube rules, simply delete the dovecot.sieve symbolic link (as root user) and add a link to your file:
sudo bash
cd /private/var/spool/imap/dovecot/sieve-scripts/<GUID_OF_USER>/
rm dovecot.sieve
ln -s roundcube.sieve dovecot.sieve

Then restart the Mail service.

Hope this helps.