Skip to content

NETWAYS/rt-extension-sessionstoreredisttl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RT::Extension::SessionStoreRedisTTL

Expiring Redis web sessions for Request Tracker 6 — plus cryptographically strong session IDs.

RT 6 can keep web sessions in Redis with $WebSessionClass = 'Apache::Session::Redis'. That backend writes every key with a plain SET and no expiry, so session keys pile up in Redis forever (a busy instance ends up with hundreds of thousands of dead keys). $AutoLogoff makes idle sessions functionally invalid but never deletes their data, and rt-clean-sessions only reaps SQL-backed sessions.

This extension ships a drop-in $WebSessionClass, RT::Session::RedisTTL, that keeps the proven Apache::Session::Redis serialization (Base64/Storable, hex IDs — so a blessed RT::CurrentUser survives the round trip) but:

  • writes keys with a Redis expiry (SET … EX), defaulting the TTL to $AutoLogoff, so idle sessions expire on their own; and
  • by default generates session IDs from the system CSPRNG instead of the weak md5(time/rand/pid) the stock backend uses.

Only the store driver and (optionally) the ID generator change. The serialized payload and ID format are identical to Apache::Session::Redis, so existing sessions stay readable and valid — rolling this out logs nobody out.

Why not Apache::Session::Browseable::Redis

It supports a TTL out of the box, but is hardcoded to a JSON serializer (to_json without convert_blessed). RT stores a blessed RT::CurrentUser in the session; JSON silently drops it on the round trip, so the session comes back broken. The problem is purely the serializer — so this extension keeps Base64/Storable and adds the TTL at the store layer instead.

Installation

perl -I. Makefile.PL    # -I. is required: modern Perl drops "." from @INC
make
make install            # may need root

Then add to /opt/rt/etc/RT_SiteConfig.pm:

Plugin('RT::Extension::SessionStoreRedisTTL');
Set( $WebSessionClass, 'RT::Session::RedisTTL' );
Set( %WebSessionProperties, server => '127.0.0.1:6379' );

Activating the plugin is required — it puts the extension's lib/ on @INC, which is how the store driver gets found (it is loaded by name at request time). Then clear the Mason cache (rm -rf /opt/rt/var/mason_data/obj) and restart the webserver.

Configuration

TTL

The key TTL (seconds) is resolved in this order:

  1. an explicit TTL in %WebSessionPropertiesTTL => 0 opts out (plain SET, no expiry);
  2. else $AutoLogoff * 60 — the idle window after which RT logs the user out — if $AutoLogoff is set and non-zero;
  3. else an 8h floor. RT's $AutoLogoff defaults to 0 (off), so this guarantees keys always expire instead of accumulating forever.
Set( %WebSessionProperties,
    server => '127.0.0.1:6379',
    TTL    => 43200,   # seconds; optional, see resolution order above
);

update is aliased to insert, so the TTL is refreshed on every write — a sliding idle expiry; active sessions are never reaped. Pick a TTL >= $AutoLogoff so an idle key does not vanish before RT's own logout window.

$RedisSessionSecureID (default: on)

Session IDs are drawn from the system CSPRNG. To fall back to the legacy MD5 generator:

Set( $RedisSessionSecureID, 0 );

Security

The stock generator, Apache::Session::Generate::MD5, builds the ID as md5_hex(md5_hex( time() . {} . rand() . $$ )). Its unpredictability comes only from Perl's rand() (a non-cryptographic drand48 PRNG), an anonymous hash's address, the pid and the wall-clock second. The MD5 step adds no entropy — and switching to SHA-256 or any other digest would not help, because a hash of low-entropy input is still low-entropy. (RT's own RT::AuthToken::_GenerateToken uses the same time/rand/{} pattern with SHA-512.)

So this extension sources IDs from the OS CSPRNG (Crypt::URandom: getrandom(2) / /dev/urandom) by default, keeping the 32-hex-character format so the inherited validator still accepts old MD5 IDs. It is a strict security improvement with no compatibility cost.

The TTL value comes from configuration ($AutoLogoff or an explicit TTL), never from anything client-supplied, and is validated to a positive integer before it reaches Redis.

Migrating existing keys

Old keys written without a TTL persist until they are next written (then they gain one). To retire the accumulated keyspace in one go, flush the session DB during a maintenance window before cutover — this only logs everyone out, it does not lose ticket data:

redis-cli -n 0 FLUSHDB

Requirements

License

GPL v2. Copyright (c) 2026 NETWAYS GmbH.

About

Expiring Redis web sessions for Request Tracker 6, with CSPRNG session ids

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages