We use cookies to ensure that we give you the best experience on our website. By continuing to use the website you agree for the use of cookies for better website performance and a personalized experience.

Implementing Basic Role-Based Access Control (RBAC) in Apache Druid

Anna Strukova
.
February 27, 2024
Implementing Basic Role-Based Access Control (RBAC) in Apache Druid
Anna Strukova
February 27, 2024
.
X MIN Read
February 27, 2024
.
X MIN Read
February 27, 2024
.
X MIN Read

Apache Druid stands out as a powerful open-source data store renowned for its real-time analytics capabilities. While its performance and scalability of Apache Druid make it ideal for handling large volumes of data, ensuring proper security measures is crucial for protecting sensitive information and controlling access to resources. In this tutorial, we will walk through the process of setting up Basic Role-Based Access Control (RBAC) in Druid. RBAC is a security mechanism that allows you to control access to resources based on roles assigned to users.

Installing and Running Apache Druid

First, let's get Apache Druid up and running:

1. Download Druid: Begin by downloading the latest version of Druid from the official website. In our example we use Apache Druid 28.0.1 release.

2. Extract Files: Use the following command to extract the downloaded file:

 tar -xzf apache-druid-28.0.1-bin.tar.gz 

Ensure Java 8u92+ or versions 11 or 17 are installed, and set the JAVA_HOME environment variable.

3. Run Druid: Navigate to the Druid directory and start the micro-quickstart configuration:

 cd apache-druid-28.0.1
./bin/start-micro-quickstart 

Configure Basic Authentication

In our tutorial, we’re running Druid using a micro-quickstart configuration. To configure basic authentication, edit the 'common.runtime.properties' file located in 'conf/druid/single-server/micro-quickstart/_common/':

1. Add the druid-basic-security extension to 'druid.extensions.loadList' in 'common.runtime.properties':

 druid.extensions.loadList=["druid-basic-security", "druid-histogram", "druid-datasketches", "druid-kafka-indexing-service"] 

2. Configure the basic Authenticator, Authorizer, and Escalator settings.

Example of configuration of HTTP basic authentication:

 # Druid basic security
druid.auth.authenticatorChain=["MyBasicMetadataAuthenticator"]
druid.auth.authenticator.MyBasicMetadataAuthenticator.type=basic

# Default password for 'admin' user, should be changed for production.
druid.auth.authenticator.MyBasicMetadataAuthenticator.initialAdminPassword=password1

# Default password for internal 'druid_system' user, should be changed for production.
druid.auth.authenticator.MyBasicMetadataAuthenticator.initialInternalClientPassword=password2

# Uses the metadata store for storing users.
# You can use the authentication API to create new users and grant permissions
druid.auth.authenticator.MyBasicMetadataAuthenticator.credentialsValidator.type=metadata

# If true and if the request credential doesn't exist in this credentials store,
# the request will proceed to next Authenticator in the chain.
druid.auth.authenticator.MyBasicMetadataAuthenticator.skipOnFailure=false

druid.auth.authenticator.MyBasicMetadataAuthenticator.authorizerName=MyBasicMetadataAuthorizer

# Escalator
druid.escalator.type=basic
druid.escalator.internalClientUsername=druid_system
druid.escalator.internalClientPassword=password2
druid.escalator.authorizerName=MyBasicMetadataAuthorizer

druid.auth.authorizers=["MyBasicMetadataAuthorizer"]

druid.auth.authorizer.MyBasicMetadataAuthorizer.type=basic 

3. Restart Druid for changes to take effect.

Note: If Druid was previously running without authentication, delete the 'var' directory from the Druid root directory before restarting.

Configuring RBAC

Now that basic authentication is configured, we can proceed to set up RBAC by creating users, roles, and permissions via the Druid Coordinator 'user' endpoint.

Note: you cannot assign permissions directly to individual users. They must be assigned through roles.

We'll create three users, each associated with a specific role:

  • Admin User: This user possesses administrative permissions.

Username: admins

Password: admin_123

Role: adminrole

  • Reader All User: This user can read data from all datasources.

Username: reader_all

Password: pass_All

Role: readallrole

  • Reader One User: This user has permission to read one particular datasource, in our case, "wikipedia".

Username: reader_one

Password: pass_One

Role: readonerole

Step-by-step guide to setting up RBAC on 'localhost' with coordinator API 8081.

Note: The default Coordinator API port is 8081 for non-TLS connections and 8281 for secured connections.

1. Creating Users:

Users are created by issuing POST requests to the Druid Coordinator user endpoint 'druid-ext/basic-security/authentication/db/MyBasicMetadataAuthenticator/users/<USERNAME>', specifying the username.

Example:

 curl -u admin:password1 -XPOST http://localhost:8081/druid-ext/basic-security/authentication/db/MyBasicMetadataAuthenticator/users/admins 
 curl -u admin:password1 -XPOST http://localhost:8081/druid-ext/basic-security/authentication/db/MyBasicMetadataAuthenticator/users/reader_all 
 curl -u admin:password1 -XPOST http://localhost:8081/druid-ext/basic-security/authentication/db/MyBasicMetadataAuthenticator/users/reader_one 

2. Adding Credentials:

Credentials (passwords) are added for each user by issuing a POST request to 'druid-ext/basic-security/authentication/db/MyBasicMetadataAuthenticator/users/<USERNAME>/credentials'.

Example:

 curl -u admin:password1 -H'Content-Type: application/json' -XPOST http://localhost:8081/druid-ext/basic-security/authentication/db/MyBasicMetadataAuthenticator/users/admins/credentials --data-raw '{"password": "admin_123"}' 
 curl -u admin:password1 -H'Content-Type: application/json' -XPOST http://localhost:8081/druid-ext/basic-security/authentication/db/MyBasicMetadataAuthenticator/users/reader_all/credentials --data-raw '{"password": "pass_All"}' 
 curl -u admin:password1 -H'Content-Type: application/json' -XPOST http://localhost:8081/druid-ext/basic-security/authentication/db/MyBasicMetadataAuthenticator/users/reader_one/credentials --data-raw '{"password": "pass_One"}' 

3. Creating Authorizer Users:

For each authenticator user you create, create a corresponding authorizer user by issuing a POST request to 'druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/users/<USERNAME>'.

Example:

 curl -u admin:password1 -XPOST http://localhost:8081/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/users/admins 
 curl -u admin:password1 -XPOST http://localhost:8081/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/users/reader_all 
 curl -u admin:password1 -XPOST http://localhost:8081/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/users/reader_one 

4. Creating Roles:

Create authorizer roles to control permissions by issuing a POST request to 'druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/roles/<ROLENAME>'.

Example:

 curl -u admin:password1 -XPOST http://localhost:8081/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/roles/adminrole 
 curl -u admin:password1 -XPOST http://localhost:8081/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/roles/readallrole 
 curl -u admin:password1 -XPOST http://localhost:8081/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/roles/readonerole 

5. Assigning roles to users:

Assign roles to users by issuing a POST request to 'druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/users/<USERNAME>/roles/<ROLENAME>'.

Example:

 curl -u admin:password1 -XPOST http://localhost:8081/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/users/admins/roles/adminrole | jq 
 curl -u admin:password1 -XPOST http://localhost:8081/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/users/reader_all/roles/readallrole | jq 
 curl -u admin:password1 -XPOST http://localhost:8081/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/users/reader_one/roles/readonerole | jq 

6. Defining Permissions:

Create JSON files specifying permissions per role.

Example:

'perms_read_all.json':

 [
   {
     "resource": {
       "type": "DATASOURCE",
       "name": ".*"
     },
     "action": "READ"
   },
   {
     "resource": {
       "type": "STATE",
       "name": ".*"
     },
     "action": "READ"
   },
   {
     "resource": {
       "type": "CONFIG",
       "name": ".*"
     },
     "action": "READ"
   }
] 

'perms_read_one.json':

 [
   {
     "resource": {
       "type": "DATASOURCE",
       "name": "wikipedia"
     },
     "action": "READ"
   },
   {
     "resource": {
       "type": "STATE",
       "name": "wikipedia"
     },
     "action": "READ"
   },
   {
     "resource": {
       "type": "CONFIG",
       "name": "wikipedia"
     },
     "action": "READ"
   }
] 

'perms_admin.json':

 [
   {
     "resource": {
       "type": "DATASOURCE",
       "name": ".*"
     },
     "action": "WRITE"
   },
   {
     "resource": {
       "type": "STATE",
       "name": ".*"
     },
     "action": "WRITE"
   },
   {
     "resource": {
       "type": "CONFIG",
       "name": ".*"
     },
     "action": "WRITE"
   },
   {
     "resource": {
       "type": "DATASOURCE",
       "name": ".*"
     },
     "action": "READ"
   },
   {
     "resource": {
       "type": "STATE",
       "name": ".*"
     },
     "action": "READ"
   },
   {
     "resource": {
       "type": "CONFIG",
       "name": ".*"
     },
     "action": "READ"
   }
] 

7. Attaching Permissions to Roles:

Assign permissions to roles to control to control how they can interact with Druid at 'druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/roles/<ROLENAME>/permissions'.

Example:

 curl -u admin:password1 -H'Content-Type: application/json' -XPOST --data-binary @perms_admin.json http://localhost:8081/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/roles/adminrole/permissions 
 curl -u admin:password1 -H'Content-Type: application/json' -XPOST --data-binary @perms_read_all.json http://localhost:8081/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/roles/readallrole/permissions 
 curl -u admin:password1 -H'Content-Type: application/json' -XPOST --data-binary @perms_read_one.json http://localhost:8081/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/roles/readonerole/permissions 

Testing RBAC

After setting up RBAC, it's essential to test the configuration:

1. Load Sample Data: Load sample data as shown here Quickstart (local) | Apache® Druid ('wikipedia'). Load datafrom sample data in the same way.

2. Check Users: Use CURL commands to verify the creation of users and their roles.

To see all created users' names:

 curl -u admin:password1 http://localhost:8081/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/users 

To see the name and role information of the user with name {reader_all}:

 curl -u admin:password1 http://localhost:8081/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/users/reader_all?full 

3. Perform Queries: Test unauthorized and authorized queries to ensure proper access control.

  • Perform an unauthorized query:
 curl "http://localhost:8888/druid/v2/sql" \
--header 'Content-Type: application/json' \
--data '{
    "query": "SELECT * FROM wikipedia WHERE user='\''BlueMoon2662'\''",
    "context" : {"sqlQueryId" : "request01"},
    "header" : true,
    "typesHeader" : true,
    "sqlTypesHeader" : true
}' 

You receive an error:

  • Perform an authorized query as 'reader_one', who has permission to read 'wikipedia' datasource:
 curl "http://localhost:8888/druid/v2/sql" \
--header 'Content-Type: application/json' \
--data '{
    "query": "SELECT * FROM wikipedia WHERE user='\''BlueMoon2662'\''",
    "context" : {"sqlQueryId" : "request01"},
    "header" : true,
    "typesHeader" : true,
    "sqlTypesHeader" : true
}' \
-u "reader_one:pass_One" 

You have an output:

  • Finally, perform a query as 'reader_one', but to retrieve data from 'kttm1' datasource:

curl "http://localhost:8888/druid/v2/sql" \
--header 'Content-Type: application/json' \
--data '{
    "query": "SELECT * FROM kttm1",
    "context" : {"sqlQueryId" : "request01"},
    "header" : true,
    "typesHeader" : true,
    "sqlTypesHeader" : true
}' \
-u "reader_one:pass_One"

You have an output:

Conclusion

Implementing basic authentication and RBAC in Apache Druid allows you to effectively manage resource access within your cluster. Regularly review and update security configurations to adapt to evolving requirements and mitigate potential threats. With robust security measures in place, you can confidently deploy Apache Druid in production environments while safeguarding data integrity and confidentiality.

By following this tutorial, you'll establish a solid foundation for securing your Apache Druid deployment and ensuring compliance with security standards.

Subscribe and stay in the loop with the latest on Druid, Flink, and more!

Thank you for joining our newsletter!
Oops! Something went wrong while submitting the form.
Deep.BI needs the contact information you provide to contact you. You may unsubscribe at any time. For information on how to unsubscribe and more, please review our Privacy Policy.

You Might Also Like