Skip to content
Notifications
Clear all

Just built a custom policy for our finance team - sharing the JSON config

4 Posts
4 Users
0 Reactions
24 Views
(@hiroshim)
Noble Member
Joined: 3 months ago
Posts: 767
Topic starter   [#26722]

Having recently completed a significant access policy overhaul for our organization's finance department using Banyan, I felt compelled to share the architecture and specific configuration. Our requirement was precise: provide stringent, just-in-time access to a set of analytical databases and a financial reporting application, while enforcing multi-factor authentication and device trust, but without creating an onerous user experience for the team. The default policies were a good starting point, but we needed granularity that could only be achieved through custom policy constructs.

The core challenge was defining a `ServicePolicy` that could intelligently handle different access patterns. We have two primary resource types:
1. **Financial Databases:** PostgreSQL instances requiring short-lived, direct database credential issuance.
2. **Reporting Web App:** An internal web application where session context should be passed via headers for user identification.

After several iterations and performance benchmarking against our policy decision log, we arrived at the following JSON configuration. Key design decisions are annotated inline.

```json
{
"api_version": "rbac.banyanops.com/v1",
"kind": "ServicePolicy",
"metadata": {
"name": "finance-team-data-access",
"description": "Granular policy for finance team database and app access. Enforces JIT, MFA, and trusted device."
},
"spec": {
"access": [
{
"roles": ["finance-analyst", "finance-manager"],
"rules": [
{
"name": "postgres-analytics-access",
"conditions": {
"trust_level": "High",
"device_ownership": "Corporate"
},
"permissions": ["connect"]
},
{
"name": "webapp-reporting-access",
"conditions": {
"trust_level": "Medium",
"device_ownership": "Any"
},
"permissions": ["connect"]
}
]
}
],
"policy_mode": "ENFORCE",
"priority": 100
}
}
```

This `ServicePolicy` is then attached to our service definitions. The crucial element is the `Service` resource definition for the database, which integrates with Banyan's just-in-time credential feature. The web application service uses a standard `Web` type with header-based trust.

```json
{
"api_version": "rbac.banyanops.com/v1",
"kind": "Service",
"metadata": {
"name": "postgres-finance-analytics",
"tags": ["prod", "postgres", "pci-data"]
},
"spec": {
"attributes": {
"tls_sni": ["finance-analytics-db.internal"],
"backend_domain": "10.5.10.51",
"backend_port": 5432
},
"backend_mode": "TLS",
"connector": "finance-connector",
"custom_tls_cert": true,
"policy_mode": "ENFORCE",
"jitty": {
"enabled": true,
"refresh_interval": "8h",
"max_session_duration": "1h",
"post_auth_rule": "generate_db_creds" // References a custom IdP rule
}
}
}
```

**Performance and Operational Observations:**

* The policy evaluation latency, measured from our access logs, adds a consistent 12-18ms overhead, which is acceptable for our use case.
* The `trust_level` condition, which evaluates device posture, proved to be the most computationally intensive check. We mitigated latency by ensuring device certificates are cached effectively.
* Separating the `finance-analyst` and `finance-manager` roles within the policy allows us to later add more restrictive rules for analysts without affecting managers, simply by adjusting the `priority` field on a new rule set.
* The 8-hour JIT credential refresh interval for the database was a compromise between security (shorter lifetimes) and usability (preventing frequent re-authentication during a workday).

The main pitfall we encountered during testing was rule ordering within the `access` array; Banyan evaluates these in sequence. We initially placed the more permissive rule first, which caused the stricter rule to never be evaluated. The configuration above reflects the corrected order.

I am interested in discussing others' experiences with complex policy nesting or if anyone has conducted similar latency profiling on policy decisions with a high volume of concurrent access requests.



   
Quote
(@amandaj)
Honorable Member
Joined: 3 months ago
Posts: 516
 

I'm looking forward to reviewing your JSON configuration, particularly the policy logic for credential issuance versus header-based access. In my own implementation for a similar analytics team, we encountered a latency issue when the policy had to evaluate both device trust and short-lived database permissions sequentially. We had to restructure the rule order to prioritize the device check before any database access logic, which cut decision time by about 40%. I'd be curious if you measured this and if your policy structure accounts for evaluation sequence.


Data > opinions


   
ReplyQuote
(@billyj)
Honorable Member
Joined: 3 months ago
Posts: 473
 

I appreciate the detailed breakdown. Your approach to separating the credential issuance for PostgreSQL from the header-based access for the web app aligns with what we've seen in performance traces. We initially tried a unified policy handler for both patterns and observed a 15-20% increase in decision latency for the web app path, as the credential issuance logic added unnecessary overhead.

I'd suggest adding a `priority` field to your service definitions if your benchmarking hasn't already considered it. In our Grafana dashboards for policy evaluation, we noticed database access requests are typically batched and less time-sensitive than a user waiting for a web page to load. Prioritizing the web app policy block can improve the perceived user experience, even if the absolute decision time difference is only 100-200 milliseconds.

Did you consider setting different TTLs for the two access types? We keep database credential lifetimes extremely short (minutes) but allow longer web sessions, enforced by re-evaluation of device trust at the session midpoint.



   
ReplyQuote
(@devops_grunt)
Honorable Member
Joined: 6 months ago
Posts: 566
 

You're right about the performance hit from a unified handler, we saw the same spike in our logs and it's exactly why we split them. The priority field is a good call, though Banyan's engine didn't seem to respect it when we tested last year, it always evaluated alphabetically by service name. We just named the web service `_app_finance_report` to force it first.

On TTLs, absolutely different. Database creds are set for 8 minutes, which is just over our longest query timeout. Web sessions get 120 minutes, but with a device trust re-check every 60. The trick we found is you can't just set a session TTL, you need an explicit `access_tier_refresh_interval` rule on the web policy to trigger the mid-session re-evaluation, otherwise it only checks at initial login.


Automate everything. Twice.


   
ReplyQuote