TSEC / Evaluate it

Evaluate TSEC in an afternoon

For the engineer or architect who has been handed this and asked for a verdict. It is time-boxed, it runs entirely in your own cluster, and it ends with a section telling you how to attack the thing and what should happen when you do. No account, no sales call, and nothing about your evaluation reaches us.

On this page

  1. What you will have at the end
  2. Before you start
  3. Install the chart
  4. Run your first expedition
  5. Put a real OIDC client in front of it
  6. Bind a device and read the decision
  7. Try to break it
  8. What this does and doesn't prove

What you will have at the end

A working deployment in your own cluster where:

If you get to the end of step 4 and that last point isn't true, we have failed the evaluation and you should tell us so.

Before you start

You need: a Kubernetes cluster you can install into (kind, minikube, k3s or a real one), kubectl, helm 3.8 or newer for OCI support, and a browser. Postgres comes with the chart; point it at your own if you prefer.

Budget about four hours. Roughly 30 minutes to a running stack and the rest spent on the parts that actually tell you something.

Two honest caveats

Registry access. Images and the chart are published to GitHub Container Registry. If a pull returns 401 or 403, that is on us, not on your setup — email sales@tricaso.com and we will sort access out.

The builder needs a licence key. The authoring console is read-only without one, so an evaluation that includes building a flow needs a key from us. The runtime does not check a licence and never will, so anything you publish keeps running regardless. Ask for an evaluation key when you ask for registry access.

The walkthrough

1 Install the chart ~15 min

Generate a master key first. The chart will not render without one:

openssl rand -base64 32
helm upgrade --install tsec oci://ghcr.io/tricasollc/charts/tsec \
  --version 26.10.0 \
  --namespace tsec --create-namespace \
  --set secret.masterKey="$(openssl rand -base64 32)" \
  --set secret.databasePassword="$(openssl rand -base64 24)"

That brings up the runtime, the builder and Postgres. The OIDC server (tsecAuth), the login front-end (tsecIdp), the SDK harness and the mock user store all default to off — you turn on only what you are assessing. We enable two of them in step 3.

One thing worth noticing while it comes up: that master key is not optional and not defaulted. The chart refuses to render without it and rejects the old CHANGE_ME_… placeholder outright, and every service independently refuses to start on a known, blank or short key. One secret signs admin tokens and identity assertions and encrypts the secret store, so a guessable value means no security at all — we would rather fail your install than hand you a facade.

Expect: pods Running in namespace tsec, and the builder reachable on a port-forward. Migrations apply on startup; no manual database step.

2 Run your first expedition ~20 min

Port-forward the builder and sign in with the bootstrap admin. Open the seeded expedition — a START → SCREEN → SCREEN → COMPLETE login — and run it with the in-app Try it harness.

Then change something: add a DECISION node that branches on a field, and publish. Publishing creates an immutable, content-hashed version; the previous one stays exactly where it was.

The thing to understand here is the division of labour. The runtime decides what happens next and returns data; your application decides what it looks like. There are no TSEC screens shipped into your UI. Expressions are scoped — session, field, nodes.<id>.output, response, device, risk, env — so what a node can read is bounded and legible.

Expect: a published version you can diff, roll back and re-run, and a run log entry per execution.

3 Put a real OIDC client in front of it ~30 min

Enable the authorization server and the login front-end, and the mock user store so you have somebody to sign in as:

helm upgrade tsec oci://ghcr.io/tricasollc/charts/tsec \
  --version 26.10.0 --namespace tsec --reuse-values \
  --set tsecAuth.enabled=true \
  --set tsecIdp.enabled=true \
  --set mockUsers.enabled=true

mockUsers is a test stand-in, not a product. In a real deployment your directory stays where it is and the flow reaches it with an API-call module.

Check discovery, then register a client and drive a normal authorization-code login with PKCE:

curl -s https://<your-auth-host>/.well-known/openid-configuration | jq .

You will get the endpoints you expect — /oauth2/authorize, /oauth2/token, /oauth2/jwks, /userinfo — because this is Spring Authorization Server underneath, not a homegrown implementation. PKCE with S256 is required, not optional. The id_token is signed RS256 and verifiable against the published JWKS.

The point of this step: the login behind that standards-compliant flow is the expedition from step 2. Change the flow, and every downstream application's login changes, with no redeploy of anything.

Expect: a valid id_token whose signature verifies against JWKS, carrying the subject and the claims your flow chose to assert.

4 Bind a device and read the decision ~30 min

This is the step that tells you whether the product is real. Add device intelligence to the login flow: a device assessment node, a DECISION that routes on the result, a TOTP step on the risky branch, and a bind node on success.

Then sign in twice from the same browser.

The first sign-in should challenge you for a second factor and, on success, bind the device to the account. The second should recognise the device and skip the challenge. That is adaptive step-up doing the only thing anyone actually wants from it: less friction for the people you already recognise, without lowering the bar for anyone else.

Now open the run log for both sessions. You should be able to see which signals matched, what each contributed, which rule fired and what the resulting decision was. Compare the two runs side by side. If you cannot reconstruct why the second login skipped the factor, the explainability claim on our homepage is not true and you should hold us to it.

Expect: two runs, two different paths, and a readable per-decision evidence trail for each — stored in your database, queryable with SQL.

5 Try to break it ~45 min

Most vendor evaluation guides stop before this part. Here is what we expect you to try and what should happen. If any of these behaves differently in your install, that is a finding and we want it.

Forge a weak master key

Install with --set secret.masterKey=CHANGE_ME_TO_A_32_BYTE_BASE64_KEY, or a short string, or none at all. Expected: the chart refuses to render, and if you bypass that, every service refuses to start with an explicit error. Overriding it requires setting an opt-in flag by hand, which is deliberately an audit trail rather than a default.

Tamper with a continuation token

Capture the continuation token mid-flow, flip a byte, and resubmit. Then try replaying a valid one after the expedition version has been republished. Expected: rejection in both cases — the token is HMAC-protected, and a revision guard stops a session continuing against a definition that has changed underneath it. Also check the idle and lifetime timeouts; they default to 15 minutes and 1 hour.

Point an outbound call at your metadata service

Author an API-call node targeting http://169.254.169.254/latest/meta-data/, then try 127.0.0.1, then an internal RFC 1918 address. Expected: blocked. Loopback, link-local, cloud-metadata and private ranges are refused by default; reaching an internal host requires an explicit allowlist entry. A Kubernetes NetworkPolicy is available as a second layer, and we would rather you ran it.

Replay a signed agent request

If you are assessing the automated-client detection, capture a validly signed Web Bot Auth request and replay it. Expected: rejected by nonce replay protection. Then try spoofing a known agent's user-agent string without a signature — expected: it classifies as a hint, not as proof, and the builder told you that when you wired the node.

Verify the audit chain, then break it on purpose

Publish an expedition and change a secret, then run the chain verifier against the database. Now go into Postgres and edit one audit_event row — change an actor, a timestamp, anything — and run it again. Expected: exit 0 the first time, and the second time a non-zero exit naming the first sequence number that no longer validates. Deleting a row should be caught too. The verifier reads the chain directly and does not go through the application, which is the entire point: it has to be trustworthy when the app, or whoever operates it, is not.

Try to read a secret back out

Store an API credential, then attempt to retrieve it through the builder or its API. Expected: you cannot. The secret store is write-only to the console and AES-256-GCM encrypted at rest; flows reference secrets without ever returning them.

Brute force things

Hammer the admin login, then a TOTP verification. Expected: admin login locks out with a Retry-After, and a locked account is detected before the password is checked, so it is not a timing oracle for whether a username exists. TOTP has its own configurable attempt and lockout policy with admin unlock.

Two things you will find, stated up front

The admin consoles have no second factor yet. Sign-in is password plus lockout. The builder can change authentication logic, so treat it as a privileged administrative surface: private ingress, VPN or service mesh, never public. The chart defaults its service to ClusterIP for exactly this reason. Admin MFA is in active development.

Request rate limiting at the edge is yours today. The runtime does not yet implement first-class per-identifier throttling on expedition execution, so put rate limiting on your ingress for the public endpoints. We would rather tell you that than let you find it in a load test.

What this does and doesn't prove

If the afternoon went well, you have established: that TSEC installs and runs in your environment with no dependency on us; that a visually authored flow can drive a standards-compliant OIDC login; that device binding measurably reduces step-up for recognised devices; that risk decisions are reconstructable after the fact; and that several specific attacks fail in the way the documentation claims.

You have not established: behaviour under production load, operational cost over a year, upgrade friction across several releases, or anything about our ability to support you. Those need a longer pilot and some conversations.

Before you write your recommendation, read what TSEC cannot do yet. It is a straight list, including the gaps most likely to block a regulated deployment. The one to check against your own control requirements first: the tamper-evident audit trail and its export cover administrative actions today, but not yet end-user authentication events from the runtime. If something there is a hard requirement, it is better in your report now than discovered in month three.

Next

The brief for whoever asked you → What TSEC is, what you own, what it cannot do yet, and what a first deployment looks like. Tell us where it broke → Registry access, an evaluation licence key, or a finding from step 5 — all to the same address.