Moving the CAS server from the development environment to the test environment, and then from the test environment to production, requires a number of changes to the configuration settings to identify the servers in the new environment, update encryption keys, etc. There are also some other configuration changes that should be made (or at least considered), especially when moving to the production environment.
Update CAS configuration settings
Several configuration settings created during the course of building the servers and enabling various features are specific to the environment in which the servers were built, and need to be updated when moving to another environment:
- Several properties in
etc/cas/config/cas.proprties
must be updated with values for the new environment (in the list below, moving to the production environment is assumed):- The
cas.server.name
property must be updated with the production server’s domain name. - If the production Active Directory/LDAP servers are not the same ones as those used by the development/test environment, the
cas.authn.ldap[n].ldapUrl
andcas.authn.attributeRepository/ldapUrl
properties must be updated. ThebindDn
andbindCredential
properties may also need to be updated. - If the production environment uses different load balancers than the development/test environment, the
cas.adminPageSecurity.ip
regular expression must be updated to match the IP addresses of the production load balancers. - The
mongo.hosts
“pseudo-property” from which the MongoDB connection string is constructed must be updated to contain the list of host names of the production MongoDB replica set members. - New ticket granting cookie encryption keys (
cas.tgc.crypto.signing.key
andcas.tgc.crypto.encryption.key
) should be generated for the production environment. - New Spring Webflow encryption keys (
cas.webflow.crypto.signing.key
andcas.webflow.crypto.encryption.key
) should be generated for the production environment. - Thymeleaf caching should be enabled in the production environment by adding the
spring.thymeleaf.cache
property and setting its value totrue
.
- The
- Some properties in
etc/cas/config/management.properties
must also be updated:- The
cas.server.name
property must be updated with the production server’s domain name (sso.newschool.edu). - The
mongo.hosts
“pseudo-property” from which the MongoDB connection string is constructed must be updated to contain the list of host names of the production MongoDB replica set members.
- The
- The CAS server SSL certificate in Tomcat’s keystore must be replaced with the production SSL certificate.
- New SAML IdP metadata, encryption keys, and signing keys should be generated for the production environment and copied to
etc/cas/saml
. - Additional CAS administrative users (who will have access to the management webapp and/or the dashboard) should be added to the
etc/cas/config/admusers.properties
file. - A new Duo protected application should be created (via the Duo administration console) for the production CAS environment and the
duoIntegrationKey
,duoSecretKey
, andduoApplicationKey
components of thecas.authn.mfa.duo[n]
property inetc/cas/config/cas.properties
updated with the new values. - If the production Google Apps environment is not the same as the one used by the development/test environments, the key files in
etc/cas/google
should be regenerated and the new X.509 certificate uploaded to the production Google Apps environment.
Once all of the above changes have been made in the cas-overlay-template
directory on the master build server for the environment, the build and installation scripts should be used to install and test the updated CAS server and management webapp on the master build server, and then everything should be copied to the CAS servers.
Lock down the Tomcat ROOT application
When we initially hardened the Tomcat installation, we chose not to remove the ROOT
web application from Tomcat’s webapps
directory because it can be useful in a development/test environment to quickly determine whether Tomcat is working properly. We even [modified the application][setup_tomcat-test-the-tomcat-installation] to display the host name, IP address, and port number of the Tomcat server. This information can still be useful in a production environment for checking on load balancer issues and the like, but from a security perspective, it’s not information that should be given to the general public.
To alleviate this problem, we can add some code to the top of the /opt/tomcat/latest/webapps/ROOT/index.jsp
(/var/lib/tomcat/ROOT/index.jsp
) file around line 18, just below this line:
<%@ page session="false" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
This is the code to be added:
<%
String a = request.getRemoteAddr();
if (a != null && !a.substring(0, 10).equals("192.68.50.") &&
!a.equals("192.168.1.10") && !a.equals("192.168.1.20")) {
// response.sendRedirect("https://casdev.newschool.edu/cas/login");
// response.sendRedirect("https://castest.newschool.edu/cas/login");
response.sendRedirect("https://sso.newschool.edu/cas/login");
}
%>
The code checks the IP address of the client host accessing the page and, if it’s not the IT department subnet or the internal interface of one of the load balancers, sends an HTTP redirect to the CAS login page. With this addition, any attempt to access https://sso.newschool.edu
from a non-whitelisted host will be redirected to https://casdev.newschool.edu/cas/login
.
Note that the URL in the response.sendRedirect()
call is dependent on the environment in which this code is running.
Set a default application
Occasionally, users will inadvertently create a browser bookmark for the CAS login page when what they (usually) mean to do is create a bookmark for the service that directed them there. Eventually, this results in the user visiting the CAS login page without having been directed there by a service. When this happens, and the user successfully authenticates, he or she will end up at a generic “login successful” page rather than at the service he or she actually wanted. Fortunately, CAS allows a different destination to be configured by adding a line to etc/cas/config/cas.properties
:
cas.view.defaultRedirectUrl=https://my.newschool.edu
We have chosen to send users to MyNewSchool, the New School web portal—partly because it’s a commonly-used application that is probably (arguably?) where they meant to go anyway, but more importantly, because it’s an application where (almost) all users have an account. Sending a user to an application where he or she doesn’t have an account is even more confusing that sending him or her to the generic login success page.
Create a standard location in which to store SAML SP metadata
When we created the service registry definition for our SAML2 test client, we provided a URL for the metadataLocation
attribute, telling the CAS server that it could contact the SAML2 SP at that URL to dynamically download the SP’s metadata. This is well and good for those SPs that support it, but at least in our experience many, if not most, SAML2-based SaaS applications do not offer dynamically-downloadable metadata. Instead, customers are expected to manually download the metadata and store it somewhere locally for their SAML2 IdP (CAS) to use.
Unfortunately, CAS does not yet support storing SAML SP metadata in a high-availability location such as the database where the ticket registry and service registry are stored. Therefore, ensuring that SAML SP metadata information is replicated across all the CAS servers in the pool must be handled manually. To make this at least a bit easier, we have chosen to maintain “master” copies of SP metadata files in the CAS Maven overlay, so that they can be distributed alongside any other updates to the CAS application or configuration files.
We have created an etc/cas/saml/sp-metadata
subdirectory in the cas-overlay-template
directory, and we store all third-party metadata files there. Whenever the CAS application or configuration files are updated, this subdirectory will be included in the files distributed by the build and installation scripts we use for that purpose and extracted into /etc/cas/saml/sp-metadata/
on each of the CAS servers in the pool.
/etc/cas/saml/sp-metadata/[servicename].xml
on one of the CAS servers and manually copies it to the others with scp
. Once everything is working, someone is supposed to copy the final [servicename].xml
file back to the Maven overlay template so that it can be distributed properly in the future. We’ve forgotten this step once or twice though, so now the checklist for updating the Maven overlay (e.g., when a new version of CAS comes out) includes an item to check the servers for any new metadata files and copy them down to the overlay.Logging to Graylog
Having multiple CAS servers behind a load balancer makes tracing things through log files difficult. Even with “sticky” sessions on the load balancer, there’s no way to determine in advance which server in the pool is the one to be monitoring when trying to debug something. And if the servers are busy, going back and trying to find the one thing you needed after the fact can be difficult, as well. Since we have a Graylog server in our environment that lots of other things log to, it made sense to use that to consolidate CAS logs there as well.
Configure Graylog to accept input from CAS
To configure Graylog to accept input from CAS:
- Log into the Graylog server GUI and select System > Inputs.
- From the “Select input” drop-down, choose
GELF UDP
and click the green Launch new input button. - Fill in some configuration settings:
- Under Node, choose the Graylog node that should host this input.
- Under Title, enter something meaningful like “Production CAS servers”.
- Under Port, choose a UDP port number to listen on (the default may be okay, but we chose to use different ports for the development, test, and production pools of CAS servers).
- Leave all the other fields at their defaults.
- Click the maroon Save button.
Configure CAS to log to Graylog
To configure CAS to log to Graylog, edit the file etc/cas/config/log4j2.xml
in the cas-overlay-template
directory. First, define a socket appender by adding the following definition underneath all the <RollingFile
appender definitions and just above the <CasAppender>
definitions (around line 45):
<Socket name="graylog" host="graylog.newschool.edu" protocol="udp" port="12203">
<GelfLayout compressionType="GZIP" compressionThreshold="1024">
<KeyValuePair key="webappName" value="cas"/>
</GelfLayout>
</Socket>
Make sure that the host
attribute contains the host name (or IP address) of the Graylog server and that the port
attribute contains the value used when the new Graylog input was defined in the previous section.
Next, in the <AsyncRoot>
definition (around line 108), add a reference to the Graylog appender (the ref
attribute should have the same value as the name
attribute in the <Socket>
definition above):
<AsyncRoot level="warn">
<AppenderRef ref="casFile"/>
<AppenderRef ref="graylog"/>
<!--
For deployment to an application server running as service,
delete the casConsole appender below
-->
<!-- <AppenderRef ref="casConsole"/> -->
</AsyncRoot>
In our experience, the <AsyncRoot>
logger (cas.log
) is the only one that needs to be sent to Graylog. Everything that gets logged to the audit logger (cas_audit.log
) is also logged to the root logger, and the perfStatsLogger
(perfStats.log
) is only logging performance statistics. On the Tomcat side, catalina.out
is only helpful if the CAS application itself is failing, and if that’s happening in production, it’s probably isolated to a single server.
Install the modified Log4j2 configuration
Install the updated log4j2.xml
file on all the CAS servers:
casprod-master# cd /opt/workspace/cas-overlay-template
casprod-master# cat etc/cas/config/log4j2.xml > /etc/cas/config/log4j2.xml
casprod-master# cd /
casprod-master# for h in 01 02 03 04 05
> do
> tar cf - etc/cas/config/log4j2.xml | ssh casprod-srv${h} "cd /; tar xf -"
> done
casprod-master#
CAS monitors /etc/cas/config/log4j2.xml
for changes and picks them up automatically, so there is no need to restart the application.
Configure the management webapp to log to Graylog
Since the management webapp also runs on every server in the pool, it makes sense to send its logs to Graylog as well (it can log to the same Graylog input as the associated CAS servers). Repeat the steps above to add the Graylog <Socket>
definition and the Graylog <AppenderRef
> to etc/cas/config/log4j2-management.xml
in the cas-management-overlay
directory, and then install the modified configuration file on all the CAS servers.
Use an Extended Validation (EV) SSL certificate
To help users identify phishing scams that make use of a forged New School SSO login page, we purchased an Extendned Validation (EV) SSL certificate for our production CAS servers, which use the sso.newschool.edu host name. Because all the most popular browsers (except Safari) display the organization name associated with the certificate in the URL bar when an EV certificate is used, it’s easy to instruct users to look for this to confirm that they’re accessing the “official” login page.