48 lines
1.8 KiB
Nim
48 lines
1.8 KiB
Nim
when compileOption("threads"):
|
|
import std/[json, options, tables, unittest]
|
|
import jwt_full
|
|
|
|
type
|
|
KeyCache = Table[string, JwkSet]
|
|
WorkerInput = tuple[keys: KeyCache, passed: ptr bool]
|
|
|
|
proc useKeys(input: WorkerInput) {.thread.} =
|
|
var keys = input.keys
|
|
try:
|
|
for i in 0 ..< 50:
|
|
let key = keys["issuer"][0]
|
|
let metadata = key["metadata"].get
|
|
metadata["labels"][0].str = "worker"
|
|
var material = key.octKey
|
|
material.k[0] = '!'
|
|
|
|
# Both metadata and parsed key material remain intact after modifying
|
|
# accessor results. Each worker also signs and verifies with its copy.
|
|
if key["metadata"].get["labels"][0].getStr != "original": return
|
|
if key.octKey.k[0] == '!': return
|
|
let token = sign(payload = "payload",
|
|
header = initJoseHeader(%*{"alg": "HS256"}), key = key)
|
|
token.validate(HS256, key)
|
|
|
|
keys["issuer"].setLen(0)
|
|
input.passed[] = true
|
|
except CatchableError:
|
|
input.passed[] = false
|
|
|
|
suite "jwt_full/jwk thread isolation":
|
|
test "workers copy key caches and use their keys independently":
|
|
let node = %*{
|
|
"kty": "oct", "alg": "HS256", "kid": "original",
|
|
"k": "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY",
|
|
"metadata": {"labels": ["original"]}}
|
|
let original = {"issuer": @[initJwk(node)]}.toTable
|
|
var workers: array[4, Thread[WorkerInput]]
|
|
var passed: array[4, bool]
|
|
for i in 0 ..< workers.len:
|
|
createThread(workers[i], useKeys, (original, addr passed[i]))
|
|
joinThreads(workers)
|
|
check passed == [true, true, true, true]
|
|
check original["issuer"].len == 1
|
|
check original["issuer"][0]["metadata"].get == node["metadata"]
|
|
check original["issuer"][0].octKey.k == node["k"].getStr
|