Apereo CAS - Configuration Security with Jasypt

Posted by Misagh Moayyed on April 15, 2024 · 8 mins read ·
Content Unavailable
Your browser is blocking content on this website. Please check your browser settings and try again.

If you are running CAS in standalone mode without the presence of the Spring Cloud configuration server, you can take advantage of built-in Jasypt functionality to decrypt sensitive CAS settings.

Jasypt is a java library which allows the deployer to add basic encryption capabilities to CAS. Jasypt supplies command-line tools useful for performing encryption, decryption, etc. In order to use the tools, you may download the Jasypt distribution. Once unzipped, you will find a jasypt-$VERSION/bin directory a number of bat|sh scripts that you can use for encryption/decryption operations (encrypt|decrypt).(bat|sh).

However, an easier approach might be to use the native CAS command-line shell. The CAS command-line shell provides the ability to query the CAS server for help on available settings/modules and various other utility functions one of which is the ability to encrypt and/or decrypt settings via Jasypt. We’ll use the shell to encrypt a few settings and place them in your CAS configuration file, expecting the server to decrypt and use them as needed.

Our starting position is based on:

  • CAS 7.1.x
  • Java 21

Configuration

The CAS WAR Overlay presents a few instructions on how to download and run the shell. Once you’re in, you can take advantage of the following Jasypt-related commands:

help encrypt-value
...
help decrypt-value

So let’s encrypt a setting:

cas>encrypt-value value casuser::Misagh alg PBEWithMD5AndTripleDES \
    provider SunJCE password ThisIsMyEncryptionKey iterations 1000

==== Encrypted Value ====
{cas-cipher}mMcg02NysblAcwYI+bFRpEcHBQaVQ51J

Nice. Let’s verify that it can be decrypted back:

cas>decrypt-value value {cas-cipher}mMcg02NysblAcwYI+bFRpEcHBQaVQ51J \
    alg PBEWithMD5AndTripleDES provider SunJCE \
    password ThisIsMyEncryptionKey iterations 1000

==== Decrypted Value ====
casuser::Misagh

Next, let’s use our typical cas.properties file with the encrypted value:

cas.authn.accept.users={cas-cipher}mMcg02NysblAcwYI+bFRpEcHBQaVQ51J

Almost there…the last task is to instruct CAS to use the proper algorithm, decryption key, and other relevant parameters when attempting to decrypt settings.

# cas.standalone.configuration-security.alg=PBEWithMD5AndTripleDES
# cas.standalone.configuration-security.provider=SunJCE
# cas.standalone.configuration-security.iterations=1000
# cas.standalone.configuration-security.psw=ThisIsMyEncryptionKey

The above settings MUST be passed to CAS at runtime using either OS environment variables, system properties or normal command-line arguments. For example, you may run CAS with an embedded servlet container while passing parameters as command-line arguments:

java -jar -Dlog.console.stacktraces=true \
    build/libs/cas.war \
    --cas.standalone.configuration-security.alg=PBEWithMD5AndTripleDES \
    --cas.standalone.configuration-security.provider=SunJCE \
    --cas.standalone.configuration-security.iterations=1000 \
    --cas.standalone.configuration-security.psw=ThisIsMyEncryptionKey \
    --logging.level.org.apereo.cas=trace

More…

The shell also presents a few more Jasypt-related commands to list out algorithms, providers, etc. If you use the help command, you’d be presented with a list of available commands some of which are the following:

cas>help jasypt-list-algorithms
...
cas>help jasypt-list-providers
...
cas>help jasypt-test-algorithms
...

OpenID Connect Keystore

If your CAS server is running as an OpenID Connect Provider, you might be tasked to securely control and manage the JSON Web Keystore (JWKS) file that is generated by CAS. A typical JWKS would look like the following snippet:

{
  "keys": [
    {
      "d": "...",
      "e": "AQAB",
      "use": "sig",
      "n": "...",
      "kty": "RSA",
      "kid": "cas",
      "state": 0
    }
  ]
}

The contents of the keystore may be encrypted via CAS configuration security just like any other setting. The encrypt-value shell command accepts a file parameter that should be the path to the JWKS resource for encryption. Once you have the JWKS file encrypted, you may replace its content with the produced encrypted value:

{cas-cipher}pbmmaBoWgFqCoEDY+kiuBKGc0wmovW7bxArWfcQ/...

At runtime, CAS will automatically recognize that the file is encrypted and will attempt to decode it back to its original JSON form.

SAML2 Identity Provider Keys

If your CAS server is running as a SAML2 Identity Provider, you might be tasked to securely control and manage the encryption and signing keys that are produced by the server. Concretely, these would be idp-signing.key and idp-encryption.key files. A typical private key file would match the following snippet:

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAxua2GDhpTMW5UJic04M7P3hXPrKAKXDcoC4Wd3yMEPKUP/ot
ey7Lx/F4n7Td9z6BzBUIjUR0r8X9nta9AfWqI3DGHknFJ7WQVD+nJGzWFjSbtFYh
...

Just like before, we can use the encrypt-value shell command with a file parameter that would point to our .key files. Once you have the files encrypted, you may replace their content with the produced encrypted value:

{cas-cipher}ua2GDhpTMW5UJic04M7P3hXPrKAKXD/...

At runtime and just like before, CAS will automatically recognize that the file is encrypted and will attempt to decode it back to its original form.

Finale

I hope this review was of some help to you and I am sure that both this post as well as the functionality it attempts to explain can be improved in any number of ways. Please feel free to engage and contribute as best as you can.

Misagh Moayyed