beeta/openresty/lua/redis_helper.lua
doomtube 7f56f19e94
All checks were successful
Build and Push / build-all (push) Successful in 8m52s
Fix: Force pull images in deploy workflow
2026-01-06 23:20:31 -05:00

149 lines
No EOL
4.1 KiB
Lua

local redis = require "resty.redis"
local _M = {}
-- Cache password at module load time (works better with OpenResty)
local REDIS_PASSWORD = os.getenv("REDIS_PASS")
local function get_redis_connection()
local red = redis:new()
red:set_timeouts(1000, 1000, 1000) -- connect, send, read timeout in ms
local host = "redis" -- Will be resolved by nginx resolver
local port = tonumber(os.getenv("REDIS_PORT")) or 6379
local ok, err = red:connect(host, port)
if not ok then
ngx.log(ngx.ERR, "Failed to connect to Redis: ", err)
return nil
end
-- Select the correct Redis database (db 1, matching backend config)
local db = tonumber(os.getenv("REDIS_DB")) or 1
local res, err = red:select(db)
if not res then
ngx.log(ngx.ERR, "Failed to select Redis database: ", err)
return nil
end
-- Authenticate if password is set
if REDIS_PASSWORD and REDIS_PASSWORD ~= "" then
local res, err = red:auth(REDIS_PASSWORD)
if not res then
ngx.log(ngx.ERR, "Failed to authenticate to Redis: ", err)
return nil
end
else
ngx.log(ngx.WARN, "No Redis password set, trying without auth")
end
return red
end
local function close_redis_connection(red)
-- Put connection into pool
local ok, err = red:set_keepalive(10000, 100)
if not ok then
ngx.log(ngx.ERR, "Failed to set keepalive: ", err)
end
end
function _M.validate_stream_key(key)
-- For now, skip Redis and go directly to backend
-- This fixes the immediate issue
local http = require "resty.http"
local httpc = http.new()
local backend_url = os.getenv("BACKEND_URL") or "http://drogon-backend:8080"
local res, err = httpc:request_uri(backend_url .. "/api/stream/validate/" .. key, {
method = "GET",
timeout = 1000
})
if res and res.status == 200 then
local cjson = require "cjson"
local ok, data = pcall(cjson.decode, res.body)
if ok and data.valid then
return true
end
end
return false
end
function _M.validate_viewer_token(token, expected_stream_key)
local red = get_redis_connection()
if not red then
ngx.log(ngx.ERR, "Failed to connect to Redis for token validation")
return false
end
-- Get the stream key associated with this token
local res, err = red:get("viewer_token:" .. token)
if not res or res == ngx.null then
ngx.log(ngx.WARN, "Token not found: ", token)
close_redis_connection(red)
return false
end
close_redis_connection(red)
-- Check if the token is for the expected stream
if res ~= expected_stream_key then
-- SECURITY FIX: Redact stream keys from logs to prevent exposure
ngx.log(ngx.WARN, "Token stream mismatch. Expected hash: ", ngx.md5(expected_stream_key):sub(1, 8), " Got hash: ", ngx.md5(res):sub(1, 8))
return false
end
return true
end
function _M.refresh_viewer_token(token)
local red = get_redis_connection()
if not red then
return false
end
-- Refresh TTL to 5 minutes on each HLS segment access
local ok, err = red:expire("viewer_token:" .. token, 300)
if not ok then
ngx.log(ngx.ERR, "Failed to refresh token TTL: ", err)
end
close_redis_connection(red)
return ok
end
function _M.get_streams_to_disconnect()
local red = get_redis_connection()
if not red then
return {}
end
local res, err = red:smembers("streams_to_disconnect")
close_redis_connection(red)
if not res then
ngx.log(ngx.ERR, "Failed to get streams to disconnect: ", err)
return {}
end
return res
end
function _M.remove_stream_from_disconnect(key)
local red = get_redis_connection()
if not red then
return
end
local ok, err = red:srem("streams_to_disconnect", key)
if not ok then
ngx.log(ngx.ERR, "Failed to remove stream from disconnect set: ", err)
end
close_redis_connection(red)
end
return _M