Important
This code has been moved to StyraInc/opa-sdk-demos.
Based on the Nest framework TypeScript starter repository.
Use the Authz
decorator to add static information to the request payload sent to OPA:
@Authz(() => ({ resource: 'cat' }))
on either the class or the handler method will add
{ "resource": "cat" }
to each request payload.
There's a AuthzStatic()
variant that lets you condense this to
@Authz({ resource: 'cat' })
Feel free to
import { AuthzStatic as Authz } from '../authz/decorators/action';
if the dynamic functionality isn't required.
POST /cats
{"name": "garfield", "age": 5, "breed": "unknown"}
The entire request body can be forwarded:
@Authz(({ body }) => body)
{
"name": "garfield",
"age": 5,
"breed": "unknown"
}
Note that we can also add a static part to this:
@Authz(({ body }) => ({ ...body, action: 'create' }))
{
"name": "garfield",
"age": 5,
"breed": "unknown",
"action": "create"
}
It's also possible to select just parts of the body:
@Authz(({ body: { name } }) => ({ name, action: 'create' }))
{
"name": "garfield",
"action": "create"
}
If you want to put the body into some key on the payload, use
@Authz(({ body }) => ({ payload: body }))
{
"payload": {
"name": "garfield",
"age": 5,
"breed": "unknown"
}
}
Route parameters can also be injected:
@Get(':name')
@Authz(({ params }) => ({ ...params, action: 'get' }))
async findByName(@Param('name') name: string): Promise<Cat> {
return this.catsService.findByName(name);
}
{
"name": "garfield",
"action": "get"
}
Under the hood, the @Authz
decorator registers functions that (optionally) take a Request
parameter.
See the NestJS docs for all the fields that you can use.
Pass along the client IP via
@Authz(({ ip }) => ({ ip }))
Or one specific header,
@Authz(({ headers: { 'x-user': u } }) => ({
['x-user']: u,
}))
Use the @Decision
and @DecisionStatic
decorators to instruct the AuthzGuard on how to get a boolean decision from the OPA response:
@DecisionStatic('allowed')
will use the allow
field of an object response. So if POST /v1/data/cats/result
returns
{
"allowed": true,
"details": []
}
the AuthzGuard will use the allowed
field to make the decision.
The same be achieved using a non-static @Decision
decorator:
@Decision((r) => r['allowed'])
Note that you can also pass a function, like
function pluckAllow(r: any): boolean {
return r['allow'];
}
via
@Decision(pluckAllow)
You can use all of the result for the decision, for example
@Decision((r) => r.violations.length == 0)
$ npm install
# default env variables, corresponding to http://127.0.0.1:8181/v1/data/cats/allow
cp example.env .env
# development
$ npm run start
# watch mode
$ npm run start:dev
# production mode
$ npm run start:prod
opa run --server policies
hurl basic.hurl
(hurl
is https://hurl.dev)