Casbin Authorization¶
Summary¶
This is the technical design document of the CasbinAuthorizationMiddleware. CasbinAuthorizationMiddleware authorize the incoming requests using the attributes of HTTP requests including authenticated client information.
Motivation¶
Protecting APIs with authorization is one of the fundamental gateway features. AILERON Gateway also has to have a solution for authorization. Casbin authorization framework provides one solution for Go applications.
Goals¶
- CasbinAuthorizationMiddleware provides authorization.
- CasbinAuthorizationMiddleware can authorize APIs called from unauthenticated client using JWT.
- CasbinAuthorizationMiddleware can authorize APIs called from authenticated client using JWT.
Non-Goals¶
- Provide authorization intended for a specific use cases.
Technical Design¶
Authorizing APIs¶
CasbinAuthorizationMiddleware authorize API requests by leveraging Casbin authorization framework. It works as middleware.
This figure shows how the CasbinAuthorizationMiddleware works in the gateway. Policy and model files which are documented at models are used for authorization. CasbinAuthorizationMiddleware just pass the policy and model files and request attributions for the framework and yield authorization to the framework. An error will be returned to clients when they are unauthorized.
Following 3 information are passed to casbin with this order. These information can be used for authorization in the policy file.
claims
: Request information including authenticated client. See Claims section.URL path
: Request path obtained by http#Request.URL.method
: Request method obtained by http#Request.Method.
CasbinAuthorizationMiddleware implements core.Middleware
interface to work as middleware.
type Middleware interface {
Middleware(http.Handler) http.Handler
}
Working with authentication¶
CasbinAuthorizationMiddleware can use authenticated clients’ claims for authorization.
When the client was authenticated and obtained claims
,
the claims are saved in the request context with a string key.
The claims can be extracted and can be used for authorization.
For example, authenticated client’s claims are saved in the context like this. The key name may differ depending on the authentication method.
// Example of saving claims in a context.
// Here, r is *http.Request
ctx := context.WithValue(r.Context(), "AuthnClaims", claims)
r = r.WithContext(ctx)
CasbinAuthorizationMiddleware can extract claims from the context with the same key it was saved like below. Then, authenticated client’s claims can be used for authorization by passing it to the casbin framework.
// Example of extracting claims from a context.
// Here, r is *http.Request
claims := r.Context().Value("AuthnClaims")
This figure shows the overview how the CasbinAuthorizationMiddleware works with authentication middleware.
Claims¶
Claims or attributes that can be used for authorization are defined as follows. Extra claims may be added in the future.
All claims are accessible from policy file, for example r.sub.Auth
.
The Auth
field is filled only when the value was found in request context.
Authenticated client information is set in the Auth
field.
To extract values and pass them to casbin, extra context keys can be set in configuration.
Claim | Meaning | Go Type | Policy |
---|---|---|---|
Auth | Authenticated client claims | any (Obtained from context if any) | r.sub.Auth |
Host | Requested hostname | string | r.sub.Host |
Remote | Client ip:port | string | r.sub.Remote |
Method | HTTP method | string | r.sub.Method |
API | URL path | string | r.sub.API |
Query | URL queries | url.Values (map[string][]string ) |
r.sub.Query |
Header | Request headers | http.Header (map[string][]string ) |
r.sub.Header |
This is an example of Casbin policy.
When the Auth is a map data and contains ‘scope’ key, it will be available through r.sub.Auth
.
// Example of casbin policy.
p, "contains(mapValue(r.sub.Auth, 'role'), 'admin')", /*, GET
Adapters¶
Adapter is the component that load policy files from any policy sources, sources can be files, key-value stores, RDBs or anything else. AILERON Gateway provides file and http adapters as described below.
File adapters load policy files from local file system.
CSV files with .csv
extension should have the following format.
10 value fields v0 - v9
can be used, and others are ignored.
An example is also shown.
// CSV policy format
pType,v0,v1,v2,v3,v4,v5,v6,v7,v8,v9
p, alice, /alice/*, GET
p, admin, /foo/*, POST
g, alice, admin
JSON files with .json
extension should have the following format.
10 value fields v0 - v9
can be used, and others are ignored.
An example is also shown.
// JSON policy format
[
{
"pType": "",
"v0": "",
"v1": "",
"v2": "",
"v3": "",
"v4": "",
"v5": "",
"v6": "",
"v7": "",
"v8": "",
"v9": ""
}
]
[
{"pType":"p", "v0":"alice", "v1":"/alice/*", "v2":"GET"},
{"pType":"p", "v0":"admin", "v1":"/foo/*", "v2":"POST"},
{"pType":"g", "v0":"alice", "v1":"admin"}
]
Yaml files with .yaml
or .yml
extension should have the following format.
10 value fields v0 - v9
can be used, and others are ignored.
An example is also shown.
// YAML policy format
- pType: ""
v0: ""
v1: ""
v2: ""
v3: ""
v4: ""
v5: ""
v6: ""
v7: ""
v8: ""
v9: ""
- pType: p
v0: alice
v1: /alice/*
v2: GET
- pType: p
v0: admin
v1: /foo/*
v2: POST
- pType: g
v0: alice
v1: admin
Xml files with .xml
extension should have the following format.
10 value fields v0 - v9
can be used, and others are ignored.
An example is also shown.
// XML policy format
<policies>
<policy>
<pType></pType>
<v0></v0>
<v1></v1>
<v2></v2>
<v3></v3>
<v4></v4>
<v5></v5>
<v6></v6>
<v7></v7>
<v8></v8>
<v9></v9>
</policy>
</policies>
<policies>
<policy>
<pType>p</pType>
<v0>alice</v0>
<v1>/alice/*</v1>
<v2>GET</v2>
</policy>
<policy>
<pType>p</pType>
<v0>admin</v0>
<v1>/foo/*</v1>
<v2>POST</v2>
</policy>
<policy>
<pType>g</pType>
<v0>alice</v0>
<v1>admin</v1>
</policy>
</policies>
HTTP Adapter get policy files from REST endpoint.
The endpoint response the policy content which can be accepted by the file adapter described above. Response should have one of following Content-Type header value and status code 200 OK.
application/csv
,text/csv
application/json
,text/json
application/yaml
,text/yaml
,application/yml
,text/yml
application/xml
,text/xml
To reduce network resource consumption, return 304 NotModified
prevents error and keep using the current policy.
This is the same concept as OPA’s HTTP Polling.
Test Plan¶
Unit Tests¶
Unit tests are implemented and passed.
- All functions and methods are covered.
- Coverage objective 98%.
Integration Tests¶
Integration tests are implemented with these aspects.
- CasbinAuthorizationMiddleware works as middleware.
- CasbinAuthorizationMiddleware works with input configuration.
- CasbinAuthorizationMiddleware can authorize APIs called from unauthenticated clients using JWT.
- CasbinAuthorizationMiddleware can authorize APIs called from authenticated clients using JWT.
- CasbinAuthorizationMiddleware can used defined claims for authorization.
e2e Tests¶
e2e tests are implemented with these aspects.
- CasbinAuthorizationMiddleware works as middleware.
- CasbinAuthorizationMiddleware works with input configuration.
- CasbinAuthorizationMiddleware can authorize APIs called from unauthenticated clients using JWT.
- CasbinAuthorizationMiddleware can authorize APIs called from authenticated clients using JWT.
- CasbinAuthorizationMiddleware can used defined claims for authorization.
Fuzz Tests¶
Not planned.
Benchmark Tests¶
Not planned.
Chaos Tests¶
Not planned.
Future works¶
None.