Role-Based Access Control
This tutorial demonstrates how to use role-based access control (RBAC) using Inigo's @access
directive. This is an alternative approach to Inigo's declarative configurations for RBAC.
Configuration Setup
Service Configuration
To get started, Access-Control properties must be configured in the Service
YAML that configures the Client Configuration, as shown in this example:
kind: Service
name: demo-service
spec:
path_client_info: "header.Client-Name"
path_user_id: jwt.email
path_organization_id: jwt.org_name
schema_files:
./schema.graphql
# required Access Control properties
path_user_profile: header.X-USER-PROFILE
path_user_role: header.X-USER-ROLES
anonymous_profile: guest
anonymous_roles: [guest]
As with all Inigo YAML configurations, use inigo apply
to apply the configuration as such:
inigo apply service.yaml --label dev
Schema Separation Concept
Let's take a look at this example. We have 4 roles here: guest
, viewer
, pii
and admin
.
type Query {
login(email: String!, password: String!): String! @access(role: ["guest"])
user: User! @access(role: ["viewer"])
admin: Admin! @access(role: ["admin"])
}
type User {
name: String!
address: String!
ssn: String! @access(role: ["pii"])
}
type Admin {
userCount: Int!
}
directive @access(depth: Int, role: [String]) on FIELD_DEFINITION
Here's what each role has access:
guest
- unauthorized user - has only access toQuery.login
viewer
- authorized user - has access toQuery.user
and all fields inside the User, exceptUser.ssn
, which is restriced.pii
- authorized user - has access to theUser.ssn
field.admin
- authorized user - has access toAdmin
object.
Now let's assign access roles based on different personas. In this example, Inigo agent will enfore access-contorl based of the list rule provided in 'header.X-USER-ROLESwhich were confogired under Service Configuration's
path_user_role`. When Inigo agent sees the request it expects to see the list of roles in this header.
Now let's assign access roles based on different personas. In this example, the Inigo agent will enforce access-control based on the list of roles provided in the 'header.X-USER-ROLES', which were configured under the Service Configuration's path_user_role
- Unauthorized user
X-USER-ROLES=guest
- User
X-USER-ROLES=viewer
- User with PII access
X-USER-ROLES=viewer,pii
- Admin
X-USER-ROLES=viewer,admin
::: tip For top level objects Query, Mutation and Subscription - best practice would be to have @access directive for each field. Fields without this directive would not be accessible by anyone.
Access Denied Example
Should an unauthenticated client try to call User.name
, they will see the following error:
{
"errors": [
{
"message": "invalid access",
"path": [
"user"
]
}
],
"data": null,
"extensions": {}
}
Federated schemas
For Federated schemas the @access
directive will carry druing composition.
Introspection Configuration
In Access
configuration we specify introspection mode per profile
(not per role
). In this way, it is decoupled from actual access control and gives you ability to build RBAC as per your specific business needs.
kind: Access
name: apollo-gateway-fed-2-demo
spec:
profiles:
- name: guest
introspection_mode: partial
- name: viewer
introspection_mode: partial
- name: admin
introspection_mode: full
Remember, that in service.yaml
we configured path_user_profile
to be header.X-USER-PROFILE
. Let's attach this header to our personal requests so complete set of required headers would be:
- Unauthorized user
X-USER-ROLES=guest
X-USER-PROFILE=guest
- User
X-USER-ROLES=viewer
X-USER-PROFILE=viewer
- User with PII access
X-USER-ROLES=viewer,pii
X-USER-PROFILE=viewer
- Admin
X-USER-ROLES=viewer,admin
X-USER-PROFILE=admin
Use inigo apply
to apply the configuration as such:
inigo apply access.yaml --label dev
Conclusion
Inigo's RBAC using @access
provides an easy way to add controls to how your GraphQL API is used and introspected. Finally, @access
works with federated schemas, so RBAC can be used independently in each subgraph schema.