CentOS 7.x Deploy Apereo CAS 5.3 and integrate with AD

From Notes_Wiki
Revision as of 13:19, 15 March 2020 by Saurabh (talk | contribs)

<yambe:breadcrumb self="Deploy Apereo CAS 5.3 and integrate with AD">CentOS 7.x Apereo CAS|Apereo CAS</yambe:breadcrumb>

CentOS 7.x Deploy Apereo CAS 5.3 and integrate with AD

Install required packages

Install required packages for deploying CAS 5.3 using:

yum group mark install "Development Tools"
yum group mark convert "Development Tools"
yum install @"Development Tools"

yum -y install perl-Module-Load-Conditional
yum -y install perl-Test-Simple

git config --global user.name "Saurabh Barjatiya"
git config --global user.email "saurabh@sbarjatiya.com"
git config --global core.editor "vim"

yum -y install epel-release
yum -y install haveged
systemctl enable haveged
systemctl start haveged

yum -y install java-1.8.0-openjdk-devel
java -version
vim ~/.bashrc
  export JAVA_HOME="/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/"
  #get path using "rpm -qa | grep openjdk" followed by "rpm -ql java-1.8.0-openjdk-devel-1.8.0.242.b08-0.el7_7.x86_64 | less"

#Exit all running terminals and relogin so that JAVA_HOME is defined

#Ensure firewalld is disabled or required ports 8443 etc. are allowed in firewall
systemctl disable firewalld
systemctl stop firewalld
systemctl status firewalld


Clone CAS git repository and build 5.3 version

Clone CAS git repository and build 5.3 version using:

mkdir /opt/workspace
cd /opt/workspace

git clone https://github.com/apereo/cas-overlay-template.git
cd cas-overlay-template/
git branch
grep '<cas.version>' pom.xml    #Should result into pom.xml not found in latest branch

git branch -a   #Check all versions
git checkout 5.3
grep '<cas.version>' pom.xml
git checkout -b rndtest-casdev   #Create our own branch

./mvnw clean package
ls -l target/


Configure CAS with hostname, encryption keys, etc.

  1. Edit etc/cas/config/cas.properties #Enter hostname
  2. Generate various encryption keys as follows:
    1. Visit https://mkjwk.org/ and generate encryption key for cas.tgc.crypto.signing.key using 512 “Key Size” and select HS256 as “Algorithm”
      cas.tgc.secure: true
      cas.tgc.crypto.signing.key:
      cas.tgc.crypto.encryption.key:
      cas.webflow.crypto.signing.key:
      cas.webflow.crypto.encryption.key:
    2. From same generator generate cas.tgc.crypto.encryption.key using 256 as “Key Size” and HS256 from the “Algorithm”
    3. From same generator generate value of the cas.webflow.crypto.signing.key using HS256 key size 512
    4. For cas.webflow.crypto.encryption.key use "openssl rand -base64 16" command
  3. Edit etc/cas/config/log4j2.xml and specify '/var/log/cas' as log dir
  4. Create required folders and keystore:
    mkdir /var/log/cas
    rsync -vtrp etc/cas/ /etc/cas/
    vim /etc/hosts #Ensure entry for short hostname and FQDN for local LAN IP, if not added to DNS
    hostname <CAS-FQDN>
    vim /etc/hostname #Enter <CAS-FQDN> as hostname
    #These steps do not work perhaps due to use of wrong openssl 1.0 instead of openssl 1.1Vvvvvvvvv
    cd /etc/pki/tls/private
    openssl req -x509 -nodes -days 9999 -newkey rsa:2048 -sha256 -keyout cas.pem -out cas.pem
    openssl x509 -outform der -in cas.pem -out cas.der
    openssl pkcs12 -export -out cas.p12 -inkey cas.pem -in cas.pem -certfile cas.pem
    secret123
    keytool -importkeystore -srckeystore cas.p12 -srcstoretype pkcs12 -destkeystore keystore.jks
    changeit (Twice)
    secret123
    cp keystore.jks /etc/cas/thekeystore
    sudo keytool -import -file /etc/pki/tls/private/cas.der -alias cas -keystore $JAVA_HOME/jre/lib/security/cacerts
    changeit
    keytool -export -file /etc/pki/tls/private/cas.der -keystore /etc/cas/thekeystore -alias cas
    changeit
    Refer: https://apereo.github.io/cas/developer/Build-Process-5X.html



Install tomcat and other source based software

Install and configure tomcat using:

mkdir /opt/tomcat
cd /opt/tomcat
#Get tomcat download link from https://tomcat.apache.org/download-80.cgi
curl -LO 'http://apachemirror.wuchna.com/tomcat/tomcat-8/v8.5.51/bin/apache-tomcat-8.5.51.tar.gz'
tar xzf apache-tomcat-8.5.51.tar.gz
ln -s apache-tomcat-8.5.51 latest
mv apache-tomcat-8.5.51.tar.gz /root


cd /root
#Get openssl download link from https://www.openssl.org/source/
curl -LO 'https://www.openssl.org/source/openssl-1.1.1d.tar.gz'
tar xzf openssl-1.1.1d.tar.gz
cd openssl-1.1.1d
mkdir -p /opt/openssl/openssl-1.1.1d
ln -s openssl-1.1.1d /opt/openssl/latest
./config --prefix=/opt/openssl/openssl-1.1.1d shared
make depend
make
make test
make install_sw

cd /root
#Get apr download link from https://apr.apache.org/download.cgi
curl -LO 'http://mirrors.estointernet.in/apache//apr/apr-1.7.0.tar.gz'
tar xzf apr-1.7.0.tar.gz
cd apr-1.7.0
mkdir -p /opt/apr/apr-1.7.0
ln -s apr-1.7.0 /opt/apr/latest
./configure --prefix=/opt/apr/apr-1.7.0
make
make test
make install

cd /root
tar xzf /opt/tomcat/apache-tomcat-8.5.51/bin/tomcat-native.tar.gz
cd tomcat-native-1.2.23-src/native/
./configure --with-java-home=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/ \
--with-apr=/opt/apr/latest/bin/apr-1-config \
--with-ssl=/opt/openssl/latest \
--prefix=/opt/tomcat/apache-tomcat-8.5.51
make
make install

cd /root
tar xzf /opt/tomcat/apache-tomcat-8.5.51/bin/commons-daemon-native.tar.gz
cd commons-daemon-1.2.2-native-src/unix
./configure --with-java=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/
make
cp jsvc /opt/tomcat/apache-tomcat-8.5.51/bin/

cd /opt/tomcat/latest
cp -rp conf /etc/tomcat
rm -rf conf
ln -s /etc/tomcat conf

cd /opt/tomcat/latest
cp -rp logs /var/log/tomcat
rm -rf logs
ln -s /var/log/tomcat logs

cd /opt/tomcat/latest
cp -rp webapps /var/lib/tomcat
rm -rf webapps
ln -s /var/lib/tomcat webapps
mv webapps/webapps/* webapps/
rmdir webapps/webapps/

cd /opt/tomcat/latest
mkdir /var/cache/tomcat
cp -rp work /var/cache/tomcat/work
rm -rf work
ln -s /var/cache/tomcat/work work
rmdir work/work

cd /opt/tomcat/latest
cp -rp temp /var/cache/tomcat/temp
rm -rf temp
ln -s /var/cache/tomcat/temp temp
mv temp/temp/* temp/
rmdir temp/temp/


groupadd -r tomcat
usermod -d /opt/tomcat -g tomcat -s /sbin/nologin tomcat
getent passwd tomcat

mkdir -p /opt/tomcat/latest/conf/Catalina/localhost

for dir in . conf webapps
do
cd /opt/tomcat/latest/$dir
chown -R root.tomcat .
chmod -R u+rwX,g+rX,o= .
chmod -R g-w .
done

for dir in logs temp work
do
cd /opt/tomcat/latest/$dir
chown -R tomcat.tomcat .
chmod -R u+rwX,g+rX,o= .
chmod -R g-w .
done

cd /opt/tomcat/latest
rm -rf temp/* work/*
cd webapps
rm -rf docs examples host-manager manager


Configure tomcat

  1. Edit /opt/tomcat/latest/conf/server.xml and set
    <Server port="-1" shutdown="SHUTDOWN">
    <Host name="localhost" appBase="webapps" unpackWARs="false" autoDeploy="false">
    <!-- <Connector port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" /> -->
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
    sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation"
    SSLEnabled="true" connectionTimeout="20000" maxThreads="150">
    <SSLHostConfig
    ciphers="ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS"
    honorCipherOrder="true" protocols="all,-SSLv2Hello,-SSLv2,-SSLv3"
    disableSessionTickets="true">
    <Certificate certificateKeystoreFile="/opt/tomcat/keystore.jks" certificateKeystorePassword="changeit" type="RSA" />
    </SSLHostConfig>
    <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
    </Connector>
    <!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"
    /> -->
  2. cp /etc/cas/thekeystore /opt/tomcat/keystore.jks
  3. cd /opt/tomcat/
  4. chown root.tomcat keystore.jks
  5. chmod 640 keystore.jks
  6. Edit /opt/tomcat/latest/conf/web.xml and insert
    <async-supported>true</async-supported>
    before "</servlet>" for default and jsp servlets
  7. Edit /opt/tomcat/latest/conf/context.xml and insert
    <Resources cachingAllowed="true" cacheMaxSize="40960" cacheTtl="60000" />
    before "</Context>"
  8. Edit /opt/tomcat/latest/conf/catalina.properties and search for jarsToSkip and update below line
    jmx-tools.jar,jta*.jar,mail*.jar,slf4j*.jar,\
    Basically uncomment log4j jars by removing them from above line
  9. Create /etc/systemd/system/tomcat.service using following content:
    [Unit]
    Description=Apache Tomcat Web Application Container
    After=network.target
    [Service]
    Type=forking
    PIDFile=/var/run/tomcat.pid
    UMask=0007
    # Tomcat variables
    Environment='JAVA_HOME=/usr/lib/jvm/java-openjdk'
    Environment='CATALINA_PID=/var/run/tomcat.pid'
    Environment='CATALINA_HOME=/opt/tomcat/latest'
    Environment='CATALINA_BASE=/opt/tomcat/latest'
    Environment='CATALINA_OPTS=-Xms512M -Xmx2048M -XX:+UseParallelGC -server'
    # Needed to make use of Tomcat Native Library
    Environment='LD_LIBRARY_PATH=/opt/tomcat/latest/lib'
    ExecStart=/opt/tomcat/latest/bin/jsvc \
    -Dcatalina.home=${CATALINA_HOME} \
    -Dcatalina.base=${CATALINA_BASE} \
    -Djava.awt.headless=true \
    -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager \
    -Djava.util.logging.config.file=${CATALINA_BASE}/conf/logging.properties \
    -cp ${CATALINA_HOME}/bin/commons-daemon.jar:${CATALINA_HOME}/bin/bootstrap.jar:${CATALINA_HOME}/bin/tomcat-juli.jar \
    -pidfile ${CATALINA_PID} \
    -java-home ${JAVA_HOME} \
    -user tomcat \
    $CATALINA_OPTS \
    org.apache.catalina.startup.Bootstrap
    ExecStop=/opt/tomcat/latest/bin/jsvc \
    -pidfile ${CATALINA_PID} \
    -stop \
    org.apache.catalina.startup.Bootstrap
    [Install]
    WantedBy=multi-user.target
  10. Setup tomcat as systemd service using:
    chmod 644 /etc/systemd/system/tomcat.service
    systemctl enable tomcat.service
    systemctl start tomcat.service
    systemctl status tomcat.service
  11. Edit /opt/tomcat/latest/webapps/ROOT/index.jsp and insert this immediately after Congratulations!
    <p>Server:
    <%= request.getLocalName() %> /
    <%= request.getLocalAddr() %> /
    <%= request.getLocalPort() %></p>
    <p>Client:
    <%= request.getRemoteHost() %> /
    <%= request.getRemoteAddr() %> /
    <%= request.getRemotePort() %></p>
  12. Restart tomcat using 'systemctl restart tomcat'


Look at logs and resolve errors

JasperListener related error

  1. 'less /var/log/tomcat/catalina.YYYY-MM-DD.log' should not have any errors
  2. If there is error
    java.lang.ClassNotFoundException: org.apache.catalina.core.JasperListener
  3. Edit file /opt/tomcat/latest/conf/server.xml and comment
    <!-- <Listener className="org.apache.catalina.core.JasperListener" /> -->


OpenSSL cannot recover key error

Further due to below error

Caused by: java.lang.IllegalArgumentException: Cannot recover key
                at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:100)
                at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:72)
                at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:246)
                at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1118)
                at org.apache.tomcat.util.net.AbstractJsseEndpoint.init(AbstractJsseEndpoint.java:223)
                at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:587)
                at org.apache.coyote.http11.AbstractHttp11Protocol.init(AbstractHttp11Protocol.java:74)
                at org.apache.catalina.connector.Connector.initInternal(Connector.java:1030)
                ... 17 more
        Caused by: java.security.UnrecoverableKeyException: Cannot recover key


Delete all existing keys created so far:

rm -rf /etc/cas/thekeystore 
rm -rf /opt/tomcat/keystore.jks 
cd /etc/pki/tls/private/
ls
rm -f *

Add latest Openssl installed via source in ld path by editing '/etc/ld.so.conf' and appending:

/opt/openssl/openssl-1.1.1d/lib

Run ldconfig and check that latest openssl libraries are loaded:

ldconfig
ldconfig -p | grep openssl

Validate that latest openssl is running /opt/openssl/latest/bin/openssl version

If not edit '~/.bashrc' and prepend path for openssl installed by source to current path

export PATH=/opt/openssl/latest/bin:$PATH

Exit from all shells and reconnect. Now openssl version should be 1.1.1d


Regenerate various keystores and keys again

Regenerate various keystores and keys again using:

cd /etc/pki/tls/private
mkdir -p /opt/openssl/openssl-1.1.1d/ssl/
cp /root/openssl-1.1.1d/apps/openssl.cnf /opt/openssl/openssl-1.1.1d/ssl/

openssl req -x509 -newkey rsa:4096 -sha256 -nodes -out cacert.pem -outform PEM
#Remember various values given to create CA with case sensitivity

openssl req -nodes -newkey rsa:2048 -sha256 -keyout cas.key -out cas.csr
#Keep Organization name and other values same with case sensitivity as while creating CA

touch index.txt
echo '01' > serial.txt
vim /opt/openssl/openssl-1.1.1d/ssl/openssl.cnf
  Under [CA_default] update at least
   dir = .
   serial          = $dir/serial.txt
   private_key     = $dir/private/privkey.pem
mkdir newcerts
openssl ca -in cas.csr -out cas.crt -cert cacert.pem -keyfile privkey.pem
cat cas.crt cacert.pem > /opt/tomcat/cas-all.crt
cd /opt/tomcat
openssl pkcs12 -export -inkey /etc/pki/tls/private/cas.key -in cas-all.crt -name tomcat -out cas.p12
  changeit  (Twice)
keytool -importkeystore -srckeystore cas.p12 -srcstoretype pkcs12 -destkeystore keystore.jks
  changeit  (Thrice)
chown root.tomcat keystore.jks
chmod 640 keystore.jks

systemctl restart tomcat


Validate all errors are resolved

Now 'less /var/log/tomcat/catalina.YYYY-MM-DD.log' and validate log line similar to

04-Mar-2020 18:23:43.609 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 926 ms

is present


Test standalone CAS without tomcat

Test standalone CAS without tomcat using:

systemctl stop tomcat
cp /opt/tomcat/keystore.jks /etc/cas/thekeystore
cd /opt/workspace/cas-overlay-template
java -jar target/cas.war
  #Access server at https://<CAS-FQDN>:8443/cas and login with casuser:Mellon
  1. Ctrl-C to stop standalone cas
  2. Now start tomcat
    systemctl start tomcat
  3. Access tomcat page at https://<CAS-FDQN>:8443/
    Validate certificate details

In "less /var/log/tomcat/catalina.YYYY-MM-DD.log" validate for following logs are present

04-Mar-2020 18:30:31.636 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent Loaded APR based Apache Tomcat Native library [1.2.23] using APR version [1.7.0].
04-Mar-2020 18:30:31.637 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
04-Mar-2020 18:30:31.637 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
04-Mar-2020 18:30:31.652 INFO [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL OpenSSL successfully initialized [OpenSSL 1.1.1d  10 Sep 2019]


Create important shell-scripts

cassrv-tarball.sh

We will need below commands may times. Perhaps save them as 'cassrv-tarball.sh'

cd /opt/workspace/cas-overlay-template
tar czf /root/cassrv-files.tgz --owner=root --group=tomcat --mode=g-w,o-rwx \
    etc/cas -C target cas --exclude cas/META-INF
ls -asl /root/cassrv-files.tgz

Execute this script once.


cassrv-install.sh

We will need below commands many times. Perhaps save them as 'cassrv-install.sh'

systemctl stop tomcat
cd /
rm -rf etc/cas/config etc/cas/services
tar xzf /root/cassrv-files.tgz etc/cas
cd /opt/tomcat/latest/
rm -rf webapps/cas work/Catalina/localhost/cas
cd /opt/tomcat/latest/webapps
tar xzf /root/cassrv-files.tgz cas
systemctl start tomcat

Execute this script once.

In "less /var/log/tomcat/catalina.YYYY-MM-DD.log" look for

04-Mar-2020 19:05:37.535 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/var/lib/tomcat/cas] has finished in [41,460] ms
04-Mar-2020 19:05:37.545 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["https-openssl-nio-8443"]
04-Mar-2020 19:05:37.554 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 42398 ms

Access server at https://<CAS-FQDN>:8443/cas and login with casuser:Mellon


Commit existing build and add JSON support

Commit existing changes:

cd /opt/workspace/cas-overlay-template
git add etc/cas/config/cas.properties
git add etc/cas/config/log4j2.xml
git commit -m "Initial CAS build"

Edit pom.xml and search for dependencies and then under dependencies of default profile add dependency for json service

<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-json-service-registry</artifactId>
<version>${cas.version}</version>
</dependency>

Rebuild CAS with JSON service support using:

./mvnw clean package

Edit etc/cas/config/cas.properties and append following to enable JSON files based services from desired folder

  cas.serviceRegistry.json.location: file:/etc/cas/services

mkdir etc/cas/services

Create 'etc/cas/services/HTTPSandIMAPSwildcard-1503925297.json' with following contents:

{
/*
* Wildcard service definition that applies to any https or imaps url.
* Do not use this definition in a production environment.
*/
"@class" : "org.apereo.cas.services.RegexRegisteredService",
"serviceId" : "^(https|imaps)://.*",
"name" : "HTTPS and IMAPS wildcard",
"id" : 1503925297,
"evaluationOrder" : 99999
}

After this run shell-scripts: 1. cassrv-tarball.sh 2. cassrv-install.sh

Commit changes related to enabling JSON service registory to git:

cd /opt/workspace/cas-overlay-template
git add etc/cas/config/cas.properties
git add etc/cas/services
git add pom.xml
git commit -m "Added JSON service registry"


Add support for LDAP or AD

Edit pom.xml and add dependency for LDAP:

<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-ldap</artifactId>
<version>${cas.version}</version>
</dependency>


Rebuild CAS with LDAP support

./mvnw clean package

Edit etc/cas/config/cas.properties and append below line to disable casuser:Mellon login:\

cas.authn.accept.users:

Commit LDAP support to git

cd /opt/workspace/cas-overlay-template
git add etc/cas/config/cas.properties
git add pom.xml
git commit -m "Added LDAP support"


In etc/cas/config/cas.properties add configuration to authenticate against AD using:

cas.authn.ldap[0].order: 0
cas.authn.ldap[0].name: Active Directory
cas.authn.ldap[0].type: AUTHENTICATED
#cas.authn.ldap[0].type: AD

#Replace below with desired bind dn
cas.authn.ldap[0].bindDn=cn=Administrator,CN=Users,DC=<Domain>,DC=COM
cas.authn.ldap[0].bindCredential=<Administrator-password>
cas.authn.ldap[0].ldapUrl: ldap://<AD-Server-FQDN-or-IP>/
cas.authn.ldap[0].validatePeriod: 270
cas.authn.ldap[0].poolPassivator: BIND
cas.authn.ldap[0].searchFilter: sAMAccountName={user}
cas.authn.ldap[0].baseDn: DC=<Domain>,DC=COM
#cas.authn.ldap[0].dnFormat: cn=%s,ou=Users,DC=<Domain>,DC=COM

cas.authn.ldap[0].subtreeSearch=true
cas.authn.ldap[0].enhanceWithEntryResolver=true
cas.authn.ldap[0].derefAliases=ALWAYS

cas.authn.ldap[0].useSsl=false
cas.authn.ldap[0].useStartTls=false

Note that since in our case it is not possible to come up with dnFormat directly based on username, it is not possible to use LDAP type AD. We are using LDAP type authenticated with bind credentials and search filter to search correct user with matching sAMAccountName

Run shell-scripts: 1. cassrv-tarball.sh 2. cassrv-install.sh

  1. Open https://<CAS-FQDN>:8443/cas/login
  2. Try to login with AD user. Vaidate that only with correct password login is working.


Refer:


<yambe:breadcrumb self="Deploy Apereo CAS 5.3 and integrate with AD">CentOS 7.x Apereo CAS|Apereo CAS</yambe:breadcrumb>