Two-Factor-Authentication with OTP on CentOS 7

Originally published at: https://www.privacyidea.org/two-factor-authentication-with-otp-on-centos-7/

Attention: This HowTo is outdated! There is an improved HowTo included in the privacyIDEA documentation

This Howto describes the setup of privacyIDEA on CentOS 7 including a FreeRADIUS 3 configuration.

This Howto is provided by Patrick Hirschbühl. Thanks a lot for this contribution!

privacyIDEA + MySQL on CentOS 7

Minimal Installation of CentOS 7

yum -y install net-tools
yum -y install wget NetworkManager-tui

Example for /etc/hosts

 192.168.1.2 privacyideaserver privacyideaserver.domain

/etc/selinux/config

SELINUX=disabled

Install necessary software:

rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY*
yum -y install epel-release
yum -y install yum-priorities

Edit /etc/yum.repos.d/epel.repo

[epel]
 name=Extra Packages for Enterprise Linux 7 - $basearch
 #baseurl=http://download.fedoraproject.org/pub/epel/7/$basearch
 mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch
 failovermethod=priority
 priority=10
 enabled=1
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7

Install further software:

yum update
yum -y groupinstall 'Development Tools'
yum -y install open-vm-tools net-tools; reboot
yum install ntp -y

Optional Tools:

yum install links nmap rkhunter

privacyIDEA

yum install mariadb-server httpd mod_wsgi mod_ssl python-devel gcc mariadb-devel libjpeg-devel \
freeradius freeradius-utils freeradius-perl openldap-devel perl-libwww-perl perl-Config-IniFiles \
perl-Try-Tiny perl-Data-Dump perl-JSON perl-LWP-Protocol-http* python-virtualenv libffi-devel \
freetype-devel libpng-devel postgresql-devel

systemctl enable radiusd.service
systemctl start radiusd
systemctl enable mariadb.service
systemctl start mariadb
systemctl enable httpd.service
systemctl start httpd

Create Database

mysql_secure_installation
echo 'create database privacyidea;' | mysql -u root -p
echo 'grant all privileges on privacyidea.* to "privacyidea"@"localhost" identified by "unknown";' \
   | mysql -u root -p

Install privacyIDEA

virtualenv /opt/privacyIDEA
cd /opt/privacyIDEA
source bin/activate

Install further requirements for building packages with pip:

yum -y install libxslt-devel libxml2-devel

Download requirements.txt from https://github.com/privacyidea/privacyidea/blob/master/requirements.txt

pip install -r requirements.txt
pip install MySQL-python
pip install privacyidea
mkdir /etc/privacyidea
mkdir /var/log/privacyidea

Edit /etc/privacyidea/pi.cfg:

# The realm, where users are allowed to login as administrators
SUPERUSER_REALM = ['super', 'administrators']
# Your database
SQLALCHEMY_DATABASE_URI = 'mysql://privacyidea:unknown@localhost/privacyidea'
# This is used to encrypt the auth_token
SECRET_KEY = 't0p s3cr3t'
# This is used to encrypt the admin passwords
PI_PEPPER = "Never know..."
# This is used to encrypt the token data and token passwords
PI_ENCFILE = '/etc/privacyidea/enckey'
# This is used to sign the audit log
PI_AUDIT_KEY_PRIVATE = '/etc/privacyidea/private.pem'
PI_AUDIT_KEY_PUBLIC = '/etc/privacyidea/public.pem'
PI_LOGFILE = '/var/log/privacyidea/privacyidea.log'
# PI_LOGLEVEL = 20
# PI_INIT_CHECK_HOOK = 'your.module.function'

Run further commands:

pi-manage.py create_enckey
pi-manage.py create_audit_keys
pi-manage.py createdb
pi-manage.py admin add admin -e admin@localhost

Add firewall rules

firewall-cmd --permanent --zone=public --add-service=http --add-service=https --add-service=radius
firewall-cmd --reload
firewall-cmd --zone=public --list-all

Test

systemctl stop httpd
pi-manage.py runserver -h Hostname-or-IP -p 80
systemctl start httpd

Create user

useradd -r -m privacyidea -d /opt/privacyIDEA

Fix rights privacyIDEA

chown -R privacyidea:root /etc/privacyidea
/opt/privacyIDEA/bin/privacyidea-fix-access-rights -f /etc/privacyidea/pi.cfg -u privacyidea
chmod 400 /etc/privacyidea/enckey
chmod 400 /etc/privacyidea/*.pem
chown -R privacyidea:root /var/log/privacyidea

privacyIDEA Apache config

mkdir -p /var/run/wsgi
cp /opt/privacyIDEA/etc/privacyidea/privacyideaapp.wsgi /etc/privacyidea
mv /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.disabled

Edit /etc/httpd/conf/httpd.conf:

ServerName Hostname-or-IP:80

Edit /etc/httpd/conf.d/privacyidea.conf:

TraceEnable off
ServerSignature Off
ServerTokens Prod
WSGIPythonHome /opt/privacyIDEA
WSGISocketPrefix /var/run/wsgi

<VirtualHost default:80>
ServerAdmin webmaster@localhost
ServerName localhost
RewriteEngine On
RewriteCond %{HTTPS} !=On
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>

<VirtualHost default:443>
ServerAdmin webmaster@localhost
ServerName localhost
DocumentRoot /var/www
<Directory />
Require all granted
Options FollowSymLinks
AllowOverride None
</Directory>

The daemon is running as user ‘privacyidea’

This user should have access to the encKey database encryption file

WSGIDaemonProcess privacyidea python-path=/etc/privacyidea:/opt/privacyIDEA/lib/python2.7/site-packages processes=1 threads=15 display-name=%{GROUP} user=privacyidea
WSGIProcessGroup privacyidea
WSGIPassAuthorization On
WSGIScriptAlias / /etc/privacyidea/privacyideaapp.wsgi
SSLEngine On
SSLProtocol All -SSLv2 -SSLv3
SSLHonorCipherOrder On
SSLCipherSuite EECDH+AES256:DHE+AES256:EECDH+AES:EDH+AES:-SHA1:EECDH+RC4:EDH+RC4:RC4-SHA:AES256-SHA:!aNULL:!eNULL:!EXP:!LOW:!MD5
SSLCertificateFile /etc/pki/tls/certs/privacyideaserver.pem
SSLCertificateKeyFile /etc/pki/tls/private/privacyideaserver.key
</VirtualHost>

Enable Apache config:

/opt/privacyIDEA/bin/privacyidea-create-certificate -f /etc/httpd/conf.d/privacyidea.conf
apachectl configtest
systemctl restart httpd

Config Freeradius 3 for privacyIDEA

cp /opt/privacyIDEA/lib64/privacyidea/authmodules/FreeRADIUS/privacyidea_radius.pm \
  /etc/raddb/mods-config/perl/

Edit /etc/raddb/mods-available/perl:

perl {
 filename = ${modconfdir}/${.:instance}/privacyidea_radius.pm
}
ln -s /etc/raddb/mods-available/perl /etc/raddb/mods-enabled/

Edit /etc/raddb/clients.conf:

client Radius-Client {
  ipaddr = 192.168.1.1/32
  secret = shared_secret_key
  require_message_authenticator = no
  nas_type = other
}

Edit /etc/raddb/sites-available/privacyidea:

server default {
 listen {
   type = auth
   ipaddr = *
   port = 0
   limit {
      max_connections = 16
      lifetime = 0
      idle_timeout = 30
   }
 }
 listen {
   ipaddr = *
   port = 0
   type = acct
   limit {
   }
 }

authorize {
preprocess
digest
suffix
ntdomain
files
expiration
logintime
pap
update control {
Auth-Type := Perl
}
}

authenticate {
Auth-Type Perl {
perl
}
digest
}

preacct {
suffix
files
}

accounting {
detail
}

session {
}
post-auth {
}
pre-proxy {
}
post-proxy {
}
}

ln -s /etc/raddb/sites-available/privacyidea /etc/raddb/sites-enabled/
rm /etc/raddb/sites-enabled/default
rm /etc/raddb/sites-enabled/inner-tunnel

Edit /etc/privacyidea/rlm_perl.ini:

[Default]
URL = https://127.0.0.1/validate/check
#REALM = someRealm
#RESCONF = someResolver
SSL_CHECK = false
#DEBUG = true

Edit /etc/raddb/mods-config/perl/privacyidea_radius.pm

our $CONFIG_FILE = “/etc/privacyidea/rlm_perl.ini”;
cp /opt/privacyIDEA/etc/privacyidea/dictionary /etc/raddb/

Test Freeradius

systemctl stop radiusd
radiusd -X
echo "User-Name=user, User-Password=password" | radclient -sx localhost auth testing123
systemctl restart radiusd

Fix rights privacyIDEA and Freeradius

chown -R privacyidea:root /etc/privacyidea
chgrp -R radiusd /etc/raddb
cd /etc/raddb
ll -Z
restorecon /etc/raddb/*

reboot 🙂

Change Password Admin User

cd /opt/privacyIDEA
source bin/activate
pi-manage.py admin change -p admin

Update privacyIDEA

cd /opt/privacyIDEA
source bin/activate
pip install --upgrade cffi
pip install --upgrade bcrypt
pip install --upgrade privacyidea