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.