/admin
GraphQL endpoint on any Alpha node.
Access Control List (ACL) provides access protection to your data stored in Dgraph. When the ACL feature is turned on, a client, e.g. dgo or dgraph4j, must authenticate with a username and password before executing any transactions, and is only allowed to access the data permitted by the ACL rules.
This document has two parts: first we will talk about the admin operations needed for setting up ACL; then we will explain how to use a client to access the data protected by ACL rules.
Turn on ACLs
The ACL Feature can be turned on by following these steps
Since ACL is an enterprise feature, make sure your use case is covered under a contract with Dgraph Labs Inc. You can contact us by sending an email to [email protected] or post your request at our discuss forum to get an enterprise license.
Create a plain text file, and store a randomly generated secret key in it. The secret key is used by Alpha servers to sign JSON Web Tokens (JWT). As you’ve probably guessed, it’s critical to keep the secret key as a secret. Another requirement for the secret key is that it must have at least 256-bits, i.e. 32 ASCII characters, as we are using HMAC-SHA256 as the signing algorithm.
Start all the alpha servers in your cluster with the option
--acl_secret_file
, and make sure they are all using the same secret key file created in Step 2.
Here is an example that starts one zero server and one alpha server with the ACL feature turned on:
dgraph zero --my=localhost:5080 --replicas 1 --idx 1 --bindall --expose_trace --profile_mode block --block_rate 10 --logtostderr -v=2
dgraph alpha --my=localhost:7080 --lru_mb=1024 --zero=localhost:5080 --logtostderr -v=3 --acl_secret_file ./hmac-secret
If you are using docker-compose, a sample cluster can be set up by:
cd $GOPATH/src/github.com/dgraph-io/dgraph/compose/
make
-
./compose -e --acl_secret <path to your hmac secret file>
, after which adocker-compose.yml
file will be generated. -
docker-compose up
to start the cluster using thedocker-compose.yml
generated above.
Set up ACL Rules
Now that your cluster is running with the ACL feature turned on, you can set up the ACL rules. This can be done using the web UI Ratel or by using a GraphQL tool which fires the mutations. Execute the following mutations using a GraphQL tool like Insomnia, GraphQL Playground or GraphiQL.
A typical workflow is the following:
- Reset the root password
- Create a regular user
- Create a group
- Assign the user to the group
- Assign predicate permissions to the group
Using GraphQL Admin API
Note All these mutations require passing an X-Dgraph-AccessToken
header, value for which can be obtained after logging in.
1) Reset the root password. The example below uses the dgraph endpoint localhost:8080/admin
as a demo, make sure to choose the correct IP and port for your environment:
mutation {
updateUser(input: {filter: {name: {eq: "groot"}}, set: {password: "newpassword"}}) {
user {
name
}
}
}
The default password is password
. groot
is part of a special group called guardians
. Members of guardians
group will have access to everything. You can add more users to this group if required.
2) Create a regular user
mutation {
addUser(input: [{name: "alice", password: "newpassword"}]) {
user {
name
}
}
}
Now you should see the following output
{
"data": {
"addUser": {
"user": [
{
"name": "alice"
}
]
}
}
}
3) Create a group
mutation {
addGroup(input: [{name: "dev"}]) {
group {
name
users {
name
}
}
}
}
Now you should see the following output
{
"data": {
"addGroup": {
"group": [
{
"name": "dev",
"users": []
}
]
}
}
}
4) Assign the user to the group
To assign the user alice
to both the group dev
and the group sre
, the mutation should be
mutation {
updateUser(input: {filter: {name: {eq: "alice"}}, set: {groups: [{name: "dev"}, {name: "sre"}]}}) {
user {
name
groups {
name
}
}
}
}
5) Assign predicate permissions to the group
mutation {
updateGroup(input: {filter: {name: {eq: "dev"}}, set: {rules: [{predicate: "friend", permission: 7}]}}) {
group {
name
rules {
permission
predicate
}
}
}
}
Here we assigned a permission rule for the friend predicate to the group. In case you have reverse edges, they have to be given the permission to the group as well
mutation {
updateGroup(input: {filter: {name: {eq: "dev"}}, set: {rules: [{predicate: "~friend", permission: 7}]}}) {
group {
name
rules {
permission
predicate
}
}
}
}
You can also resolve this by using the dgraph acl
tool
dgraph acl -a <ALPHA_ADDRESS:PORT> -w <GROOT_USER> -x <GROOT_PASSWORD> mod --group dev --pred ~friend --perm 7
The command above grants the dev
group the READ
+WRITE
+MODIFY
permission on the
friend
predicate. Permissions are represented by a number following the UNIX file
permission convention. That is, 4 (binary 100) represents READ
, 2 (binary 010)
represents WRITE
, and 1 (binary 001) represents MODIFY
(the permission to change a
predicate’s schema). Similarly, permisson numbers can be bitwise OR-ed to represent
multiple permissions. For example, 7 (binary 111) represents all of READ
, WRITE
and
MODIFY
. In order for the example in the next section to work, we also need to grant
full permissions on another predicate name
to the group dev
. If there are no rules for
a predicate, the default behavior is to block all (READ
, WRITE
and MODIFY
) operations.
mutation {
updateGroup(input: {filter: {name: {eq: "dev"}}, set: {rules: [{predicate: "name", permission: 7}]}}) {
group {
name
rules {
permission
predicate
}
}
}
}
Retrieve Users and Groups Information
Note All these queries require passing an X-Dgraph-AccessToken
header, value for which can be obtained after logging in.
The following examples show how to retrieve information about users and groups.
1) Check information about a user
query {
getUser(name: "alice") {
name
groups {
name
}
}
}
and the output should show the groups that the user has been added to, e.g.
{
"data": {
"getUser": {
"name": "alice",
"groups": [
{
"name": "dev"
}
]
}
}
}
2) Check information about a group
{
getGroup(name: "dev") {
name
users {
name
}
rules {
permission
predicate
}
}
}
and the output should include the users in the group, as well as the permissions, the group’s ACL rules, e.g.
{
"data": {
"getGroup": {
"name": "dev",
"users": [
{
"name": "alice"
}
],
"rules": [
{
"permission": 7,
"predicate": "friend"
},
{
"permission": 7,
"predicate": "name"
}
]
}
}
}
3) Query for users
query {
queryUser(filter: {name: {eq: "alice"}}) {
name
groups {
name
}
}
}
and the output should show the groups that the user has been added to, e.g.
{
"data": {
"queryUser": [
{
"name": "alice",
"groups": [
{
"name": "dev"
}
]
}
]
}
}
4) Query for groups
query {
queryGroup(filter: {name: {eq: "dev"}}) {
name
users {
name
}
rules {
permission
predicate
}
}
}
and the output should include the users in the group, as well as the permissions the group’s ACL rules, e.g.
{
"data": {
"queryGroup": [
{
"name": "dev",
"users": [
{
"name": "alice"
}
],
"rules": [
{
"permission": 7,
"predicate": "friend"
},
{
"permission": 7,
"predicate": "name"
}
]
}
]
}
}
5) Run ACL commands as another guardian (member of guardians
group).
You can also run ACL commands with other users. Say we have a user alice
which is member
of guardians
group and its password is simple_alice
.
Access Data Using a Client
Now that the ACL data are set, to access the data protected by ACL rules, we need to
first log in through a user. This is tyically done via the client’s .login(USER_ID, USER_PASSWORD)
method.
A sample code using the dgo client can be found here. An example using dgraph4j can be found here.
Access Data Using the GraphQL API
Dgraph’s HTTP API also supports authenticated operations to access ACL-protected data.
To login, send a POST request to /admin
with the GraphQL mutation. For example, to log in as the root user groot:
mutation {
login(userId: "groot", password: "password") {
response {
accessJWT
refreshJWT
}
}
}
Response:
{
"data": {
"accessJWT": "<accessJWT>",
"refreshJWT": "<refreshJWT>"
}
}
The response includes the access and refresh JWTs which are used for the authentication itself and refreshing the authentication token, respectively. Save the JWTs from the response for later HTTP requests.
You can run authenticated requests by passing the accessJWT to a request via the X-Dgraph-AccessToken
header. Add the header X-Dgraph-AccessToken
with the accessJWT
value which you got in the login response in the GraphQL tool which you’re using to make the request. For example:
mutation {
addUser(input: [{name: "alice", password: "newpassword"}]) {
user {
name
}
}
}
The refresh token can be used in the /admin
POST GraphQL mutation to receive new access and refresh JWTs, which is useful to renew the authenticated session once the ACL access TTL expires (controlled by Dgraph Alpha’s flag --acl_access_ttl
which is set to 6h0m0s by default).
mutation {
login(userId: "groot", password: "newpassword", refreshToken: "<refreshJWT>") {
response {
accessJWT
refreshJWT
}
}
}
Reset Groot Password
If you’ve forgotten the password to your groot user, then you may reset the groot password (or the password for any user) by following these steps.
- Stop Dgraph Alpha.
- Turn off ACLs by removing the
--acl_hmac_secret
config flag in the Alpha config. This leaves the Alpha open with no ACL rules, so be sure to restrict access, including stopping request traffic to this Alpha. - Start Dgraph Alpha.
-
Connect to Dgraph Alpha using Ratel and run the following upsert mutation to update the groot password to
newpassword
(choose your own secure password):upsert { query { groot as var(func: eq(dgraph.xid, "groot")) } mutation { set { uid(groot) <dgraph.password> "newpassword" . } } }
Restart Dgraph Alpha with ACLs turned on by setting the
--acl_hmac_secret
config flag.Login as groot with your new password.
This is a companion discussion topic for the original entry at https://dgraph.io/docs/enterprise-features/access-control-lists/