Multi-Tenancy with Wazuh KibanaApp

1,617 views
Skip to first unread message

Batsal Nepal

unread,
May 31, 2021, 11:34:25 PM5/31/21
to Wazuh mailing list

Hi.
Here's the scenario. I would like to implement a multi-tenant architecture of the Wazuh environment with the Elastic Stack and I'm pretty much doing it well. The only problem I have is that when I am logged in as an User A of Tenant A, s/he can still view the API properties of the other Tenants, say Tenant B, Tenant C, etc. (on different network with different Wazuh Manager for them) from the Wazuh App API configuration. Is there any mechanism to hide them so that it can be visible by the User for their specific Tenant only?

My test architecture is: 2 node elasticsearch cluster (opendistro) and a kibana (opendistro) instance with OpenID (keycloak).
Also, is this the write method to do so?
Or do you recommend to use one Wazuh Manager through out the architecture of multiple tenants?

TIA.

Alfonso Ruiz-Bravo

unread,
Jun 1, 2021, 4:28:39 AM6/1/21
to Wazuh mailing list

Hello batsal!

If I understand you correctly, what you want is that depending on the tenant with which a user connects, he/she has restricted (or no) access to the Kibana WUI (and from here to the Wazuh API), rigth?

In this case, RBAC may be the solution you need (new in Wazuh 4.0): https://documentation.wazuh.com/current/user-manual/api/rbac/index.html

With RBAC you can restrict access to the Wazuh API as needed. You can use a single Wazuh manager if you wish, saving resources and you can also use several different managers with their corresponding RBAC. Before enabling RBAC be sure to create a user with sufficient permissions to be able to manage the other RBAC resources you will need in the future once you have it enabled. 

To enable RBAC you only need to set the run_as setting to true in the /usr/share/kibana/data/wazuh/config/wazuh.yml file for each Wazuh API you have set. Example:

. . .
    hosts:
        - WazuhA:
            url: https://wazuh
            port: 55000
            username: wazuh-wui
            password: <wazuh_api_password>
            run_as: true
        - WazuhB:
            url: https://wazuh
            port: 55000
            username: wazuh-wui
            password: <wazuh_api_password>
            run_as: true
. . .


Now that you have RBAC enabled in your WUI you can restrict access to users based on their tenant. To do this, we will use the Authorization Context of each user accessing Kibana. Let's see an example of AC:


{ authContext:
{ user_name: 'userB',
is_reserved: false,
is_hidden: false,
is_internal_user: true,
user_requested_tenant: '__user__',
backend_roles: [ 'kibanauser', 'readall' ],
custom_attribute_names:
[ 'attr.internal.attribute1',
'attr.internal.attribute2',
'attr.internal.attribute3' ],
tenants: { tenantA: false, tenantB: true },
roles: [ 'kibana_user', 'own_index', 'readall' ] } }


In this case, as you want to restrict access by tenants I propose the following option: 


1. Go to the Security section in Wazuh Wui. Select Roles mapping subsection. Create new Role mapping
2. Give a distinctive name to the Role mapping you are going to create. 
3. Set the role you want for users who have this mapping. Remember that you can create additional roles.
4. Create the mapping you need according to the tenant assigned to the user.
5. Save Role Mapping.

2021-06-01 10_08_22-Window.png

In this example, we have created a Role mapping that will be applied to all users that have the Tenant tenantB set to true, which will have the role of readonly for the selected Wazuh manager API and will only be able to read/view the resources of that manager (because only that manager contains this mapping) trough WUI. If you have more managers and want to manage their access in different ways you will have to create mappings for each of them. 

Thinking about your environment, you may want to have a single manager and have several rules based on all your tenants or have several managers with rules only for the tenants that need to access your resources. 

RBAC is a complex thing to understand, I hope I have been helpful. Please do not hesitate to contact us with any questions you may have. 

Best regards,

Alfonso Ruiz-Bravo

Batsal Nepal

unread,
Jun 1, 2021, 4:45:45 AM6/1/21
to Wazuh mailing list
Hi.
Thank you very much for the information. Yes you were absolutely on point.
I will let you know if something comes up in the process.
Have a nice day :)

Batsal Nepal

unread,
Jun 2, 2021, 12:19:25 AM6/2/21
to Wazuh mailing list
Hi.
What I have been doing is, I created 2 networks (say 192.168.1.0/24 and 192.168.2.0/24), 2 separate wazuh manager for both the networks (192.168.1.254 and 192.168.2.254), and I hosted my Kibana instance on 192.168.1.10. Whenever I'm accessing the data from the Wazuh API for 192.168.1.254's wazuh manager, data loads fine. But, when I switch the API to the 192.168.2.254's wazuh manager, it is unable to load the relevant data. I have an allow all policy for both the networks.
Could you please point where have I done wrong here?
My wazuh.yml file
```
hosts:
 - thesolarsystem:
    url: https://192.168.1.254
    port: 55000
    username: wazuh-wui
    password: wazuh-wui
    run_as: true

 - uatserver:
    url: https://192.168.2.254
    port: 55000
    username: wazuh-wui
    password: wazuh-wui
    run_as: true
```
Thanks in advance.
uatserver.png
thesolarsystem.png

Batsal Nepal

unread,
Jun 2, 2021, 12:21:35 AM6/2/21
to Wazuh mailing list
And I forgot to mention, the Kibana user and role used to view them here is admin

Alfonso Ruiz-Bravo

unread,
Jun 2, 2021, 3:41:50 AM6/2/21
to Batsal Nepal, Wazuh mailing list
Hello Batsal!

The wazuh.yml configuration you have given me seems to be correct. I understand that you can not see alerts generated by the manager located on the network 192.168.2.0/24, right?

We are going to do a series of basic checks.

1- First of all, can you check if alerts are being generated in that manager? you can check it in /var/ossec/logs/alerts/alerts.json.
2- If the manager has alerts, let's check that Filebeat is reaching its destination (Elasticserach/Open Distro). To do so, you can execute the command filebeat test output.
3- If the result of the command seems correct, you can check if the alerts are being indexed in Elasticsearch. If you do not have a dedicated Elasticsearch for each Wazuh manager, try stopping the service of the manager that is fine and then run this Elasticsearch query: curl "<ELASTIC_IP>/_cat/indices?s=index". You will then be able to see the indexes that Elasticsearch has and the documents that each index has. Then generate an alert in the problematic manager (a simple restart of the service will be enough, as long as you have in your configuration a minimum level of generated alert equal to 3). Re-run the query that lists the indexes and check if the number of documents in the last wazuh-alerts index has been incremented.

With these steps, we could detect if there is a failure and where.

Finally, please note that the WUI Dashboards use the Wazuh cluster name to filter the alerts (in the Wazuh configuration, ossec.conf, you can check the cluster name setting). I tell you this, in case you do not want to have all the alerts mixed in these Dashboards and you want to have them separated by subnet. In that case, the best option would be to change the name of each Wazuh cluster in each manager and restart the service to make the changes effective.

I look forward to hearing from you.

Best regards,


WazuhAlfonso Ruiz-Bravo
Cloud computing engineer
WazuhThe Open Source Security Platform


--
You received this message because you are subscribed to a topic in the Google Groups "Wazuh mailing list" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/wazuh/2Sknm6G0xMw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to wazuh+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wazuh/9cb69f20-9144-4634-90d9-13bc77e2ee41n%40googlegroups.com.

Batsal Nepal

unread,
Jun 2, 2021, 6:04:04 AM6/2/21
to Wazuh mailing list
Hi Alfonso.

Thank you very much for the information.
I will follow the above mention steps and get back to you with my results. :)

Batsal Nepal

unread,
Jun 23, 2021, 3:25:36 AM6/23/21
to Wazuh mailing list
Hi Alfonso.
I was on a vacation so I couldn't reply you timely. Extremely sorry for the inconvenience caused.
I did follow what you mentioned and I fixed that with your kind help. :)

However, you had mentioned that with the proper implementation of RBAC, only 1 wazuh manager instance would be sufficient. My question is how shall I do it?

Let us create a scenario where there are 2 Wazuh Agents (say https://192.168.1.100 and  https://192.168.1.200) connected to the same Wazuh Manager ( https://192.168.1.254 ). Now how shall I restrict the first agent to say userA and second agent to userB?
I have been implementing "runas" and I guess I am not able to execute it properly.
Thanks in advance.

Alfonso Ruiz-Bravo

unread,
Jun 23, 2021, 5:11:33 AM6/23/21
to Batsal Nepal, Wazuh mailing list
Hello Batsal!

Thank you for your kind words and please don't apologize. I hope you had a good few days of rest.

One option to do this is to work with groups of agents, and this will be useful for more agents in the future. Let's see an example: 

1. We create groups A and B for each agent and add the agents to these groups:

GroupA -> AgentA -> https://192.168.1.100

GroupB -> AgentB ->  https://192.168.1.200

2. Now we can create the users in Open Distro, to continue with the example, these will be UserA and UserB

3. We will create the following roles: RoleA and RoleB


4. Now we will create a policy for each role, for example:

PolicyA:

{
  “actions”: “agent:read”,
  “resources”: “agent:group:GroupA”,
  “effect”: “allow”
}

PolicyB:

{
  “actions”: “agent:read”,
  “resources”: “agent:group:GroupB”,
  “effect”: “allow”
}


5. Now we must assign each policy to its corresponding role:


6. At this point we would have the roles ready. The user that has the RoleA assigned, would have access only to the agents of the GroupA group and would only be able to perform reading actions on them. The same for RoleB. Now, how can we use run_as and assign these roles to the users created in Open Distro? The answer is to create a rule and map it to the role. Let's see how it would be:

A brief explanation of the process. When a user logs into Kibana, an Authorization Context (AC) is created for that user. We will use this AC to map the user to the desired role.

AC example:

{ authContext:
   { user_name: 'kibanaro',

     is_reserved: false,
     is_hidden: false,
     is_internal_user: true,
     user_requested_tenant: '__user__',
     backend_roles: [ 'kibanauser', 'readall' ],
     custom_attribute_names:
      [ 'attr.internal.attribute1',
        'attr.internal.attribute2',
        'attr.internal.attribute3' ],
     tenants: { kibanaro: true, global_tenant: true },

     roles: [ 'kibana_user', 'own_index', 'readall' ] } }



6.1 The first step we will take is to create the rule for the mapping:

RuleA body:

{
    "name": "RuleA",
    "rule": {
        "FIND": {
            "user_name": "UserA"
        }
    }
}


RuleB body:

{
    "name": "RuleB",
    "rule": {
        "FIND": {
            "user_name": "UserB"
        }
    }
}

These rules will allow mapping users to their roles. In the example, we are mapping by the user's name user_name (in AC), but it can also be done based on the roles in Open Distro, the tenants, etc. ...


6.2 Now we have to assign the rules to their respective roles:


And we would be all set. In the example, we would have the users UserA and UserB created in Open Distro. When these users access they will have an associated AC. This AC will have as user_name UserA or UserB.

The Wazuh APP having run_as enabled will use this AC for RBAC (remember that the user set in the wazuh.yml must be able to use run_as, as for example the user wazuh-wui).

The Wazuh API will see that it has the roles RoleA and RoleB. These roles have mapping rules based on the AC user_name of the logged-in user. Therefore if the UserB logs in, it will be assigned the RoleB through RuleB, which has policies that only allow it to read the agents of the GroupB group.

I hope I have explained myself clearly and that this process has been helpful to you.

Do not hesitate to ask any questions you may have. 

Best regards,

WazuhAlfonso Ruiz-Bravo
Cloud computing engineer
WazuhThe Open Source Security Platform

Batsal Nepal

unread,
Jul 5, 2021, 12:52:01 AM7/5/21
to Wazuh mailing list
Hi!
I have been following your steps but been facing an error and some confusions.

First, do I need to authenticate each agent using the "-G" flag along with it's corresponding group name with the "ossec-agent" binary? Or can it be done within the WazuhAPP UI?

For the rest, I created a group using WazuhAPP. Then I created the required policy and roles from the WazuhAPP itself. Then, I assigned policies to role using Dev tools in UI (inside Wazuh). The query was:
```
POST /security/roles/100/policies?policy_ids=100
# where first 100 = GroupARole and second 100 = GroupAPolicy
POST /security/roles/101/policies?policy_ids=101
# where first 101 = GroupBRole and second 101 = GroupBPolicy
```
Output was:
```
No link was created to role 101 (4011) - The specified role-policy link already exist
```

Then, I created rule in ODFE for mapping using the Standard Dev tools. (not in WazuhAPP). Query was:
```
POST /security/rules
{
  "name": "GroupARuleMap",
  "rule": {
    "FIND": {
      "user_name": "userA"
    }
  }
}

POST /security/rules
{
  "name": "GroupBRuleMap",
  "rule": {
    "FIND": {
      "user_name": "userB"
    }
  }
}
```
Output was:
```
<snipped>
"result" : "created",
<snipped>
```

And finally, it was time to assign rules to roles using the Dev tools to OD. The query was:
```
POST /security/roles/101/rules?rule_ids=2
POST /security/roles/100/rules?rule_ids=2
```

Output:
```
No link was created to role 101 (4008) - The specified resource is required for a correct Wazuh's functionality.
```

Am I missing something here?
Also, why do I have to use the rule_ids=2 (ie "wui_opendistro_admin", extracted using "GET /security/rules" query)? Can you please decipher me these?

Thank you very much.
Have a great day!

Alfonso Ruiz-Bravo

unread,
Jul 5, 2021, 4:04:47 AM7/5/21
to Batsal Nepal, Wazuh mailing list
Hello Batsal!!

- First, do I need to authenticate each agent using the "-G" flag along with it's corresponding group name with the "ossec-agent" binary? Or can it be done within the WazuhAPP UI?

No such authentication is required. You can assign the agent later to a group in the Wazuh User Interface (WUI).

- No link was created to role 101 (4011) - The specified role-policy link already exist

It looks like you already have resources assigned with those IDs. You can perform the following SQL queries to your WAZUH API RBAC DB to check the contents of those queries and if the assignments make sense:

sqlite3 /var/ossec/api/configuration/security/rbac.db 'select * from roles'
sqlite3 /var/ossec/api/configuration/security/rbac.db 'select * from rules'
sqlite3 /var/ossec/api/configuration/security/rbac.db 'select * from roles_rules'

- Then, I created rule in ODFE for mapping using the Standard Dev tools. (not in WazuhAPP)

All the necessary resources are for the Wazuh API, the mapping is for the Wazuh API, you do not need to create these mapping resources in Open Distro.

The Open Distro dev tools point to the Open DIistro API and the WUI dev tools point to the Wazuh API, which is the one that has to have all the new resources.

Problems are likely to come from this part.

- No link was created to role 101 (4008) - The specified resource is required for a correct Wazuh's functionality.

This problem may be inherited from this one: - No link was created to role 101 (4011) - The specified role-policy link already exist

-  Also, why do I have to use the rule_ids=2 (ie "wui_opendistro_admin", extracted using "GET /security/rules" query)? Can you please decipher me these?

This is not correct, here the rule with ID 2 is assigned to role 100. This is an example. You would have to use:

curl -k -X POST "https://<WAZUH_API_URL>:55000/security/roles/<DESIRED_ROLE_ID>/rules?rule_ids=<DESIRED_RULE_ID>&pretty=true" -H  "accept: application/json" -H  "Authorization: Bearer $TOKEN"

In this case, you would assign your rule to the desired role using their IDs:

I hope I have clarified your doubts. If you continue to have problems, please let us know.

Best regards,
WazuhAlfonso Ruiz-Bravo
Cloud computing engineer
WazuhThe Open Source Security Platform

Batsal Nepal

unread,
Jul 6, 2021, 12:30:28 AM7/6/21
to Wazuh mailing list
Hi Alfonso.
Thank you for your prompt response.
Now my updated scenario looks like this:
1. Created 2 users (userA and userB) in ODFE with "kibanauser" privilege assigned to those users
2. Created 2 groups from the WazuhAPP (GroupA and GroupB) (id 100 and 101 respectively)
3. Created 2 policies from the WazuhAPP (PolicyA and PolicyB) {with Action=> "agent:read", Resources=> " agent:group:GroupA", and Effect=> "allow"} and {with Action=> "agent:read", Resources=> " agent:group:GroupB", and Effect=> "allow} (id 100 and 101 respectively again)
4. Created 2 roles from the WazuhAPP (RoleA and RoleB) and assigned respective Policies.
5. Assign Policies to Role using WazuhAPP Dev Tools UI:
  • POST /security/roles/101/policies?policy_ids=101
  • POST /security/roles/100/policies?policy_ids=100
6. Created Mappings with the below queries from the WazuhAPP Dev Tools UI:
POST /security/rules
{
  "name": "UserARuleMap",
  "rule": {
    "FIND": {
      "user_name": "UserA"
    }
  }
}

POST /security/rules
{
  "name": "UserBRuleMap",
  "rule": {
    "FIND": {
      "user_name": "UserB"
    }
  }
}

7. Assign rules to roles using WazuhAPP Dev Tools UI.
POST /security/roles/101/rules?rule_ids=101 #UserBRole
POST /security/roles/100/rules?rule_ids=100 #UserARole

Unfortunately, I can see both the agents in the WazuhAPP when logged in as either of the mentioned user. Maybe I'm still missing something or doing something terrible here. Could you please guide me here as well?
Thank you very much!

Alfonso Ruiz-Bravo

unread,
Jul 6, 2021, 3:21:45 AM7/6/21
to Batsal Nepal, Wazuh mailing list
Hello Batsal!


The scenario seems correct. 
It may not work because of the configuration of the Kibana APP. Could you check the wazuh.yml file? Normally it is located in the /usr/share/kibana/data/wazuh/config path. In the host section, where you add the Wazuh API settings, do you have the run_as setting enabled? If so, the added user (username) is able to use run_as (allow_run_as)? The wazuh-wui user is if you want to try with it. To be able to use RBAC correctly you need to have the run_as setting enabled and set a user that has  allow_run_as enabled. 

https://documentation.wazuh.com/current/user-manual/api/rbac/reference.html

In these links you can search and read more about run_as.

I hope I have been helpful.

Best regards, 

WazuhAlfonso Ruiz-Bravo
Cloud computing engineer
WazuhThe Open Source Security Platform

Batsal Nepal

unread,
Jul 6, 2021, 6:14:36 AM7/6/21
to Wazuh mailing list
Hi Alfonso.
Just to be sure, I checked wazuh.yml file and it indeed had the run_as option enabled. Just to be sure, I restarted Kibana as well. But now, I can neither see my authenticated agents as an admin user (not even with admin user roles), nor as a kibanauser role. Nor can I make changes to Groups as it throws me an error message attached below.

My wazuh.yml looks like this:
hosts:
  - default:
     url: https://localhost
     port: 55000
     username: wazuh
     password: wazuh
     run_as: true

Thank you.
NoGroup.PNG
NoAgents.PNG

Alfonso Ruiz-Bravo

unread,
Jul 6, 2021, 6:43:27 AM7/6/21
to Batsal Nepal, Wazuh mailing list
Hello Batsal,

These errors seem to be caused by enabling run_as and logging with a user without permissions or with insufficient permissions. Disable run_as to regain administrator control and set the user in question to have the desired permissions.

Best regards, 


WazuhAlfonso Ruiz-Bravo
Cloud computing engineer
WazuhThe Open Source Security Platform

Batsal Nepal

unread,
Jul 6, 2021, 11:19:34 PM7/6/21
to Wazuh mailing list
Hi Alfonso,
I guess I messed up real big. I logged in as the built-in "admin" user in opendistro and the problem persist. But everything is fine if I change the run_as to false.
Do I need to add something in the roles.yml or role_mappings.yml?
Thanks in advance.

Batsal Nepal

unread,
Jul 6, 2021, 11:54:32 PM7/6/21
to Wazuh mailing list
Policy:
      {
        "id": 100,
        "name": "PolicyA",
        "policy": {

          "actions": [
            "agent:read"
          ],
          "resources": [
            "agent:group:GroupA"
          ],
          "effect": "allow"
        },
        "roles": [
          100
        ]
      },
      {
        "id": 101,
        "name": "PolicyB",
        "policy": {

          "actions": [
            "agent:read"
          ],
          "resources": [
            "agent:group:GroupB"
          ],
          "effect": "allow"
        },
        "roles": [
          101
        ]
      }


Roles:
      {
        "id": 100,
        "name": "RoleA",
        "policies": [
          100
        ],
        "users": [],
        "rules": [
          100
        ]
      },
      {
        "id": 101,
        "name": "RoleB",
        "policies": [
          101
        ],
        "users": [],
        "rules": [
          101
        ]
      }


Rules:
{
        "id": 100,
        "name": "RuleAMap",
        "rule": {
          "FIND": {
            "user_name": "UserA"
          }
        },
        "roles": [
          100
        ]
      },
      {
        "id": 101,
        "name": "RuleBMap",
        "rule": {
          "FIND": {
            "user_name": "UserB"
          }
        },
        "roles": [
          101
        ]
      }

Besides this, everything else is set to default.

Alfonso Ruiz-Bravo

unread,
Jul 7, 2021, 3:40:26 AM7/7/21
to Batsal Nepal, Wazuh mailing list
Hello Batsal!

- I logged in as the built-in "admin" user in opendistro and the problem persist. But everything is fine if I change the run_as to false.

This behavior is expected. When you access with run_as active, the Wazuh API works with the AC of the connected user, in this case with the AC of the Open Distro admin. If there is no mapping for this user in the Wazuh API it is as if he does not have any permissions, if you want, you can map him by name, role or tenant and make him have a specific role, like admin if you want. 

If you disable run_as, the Wazuh APP for Kibana will use the user set in your wazuh.yml and will have the permissions of that user regardless of the actual user accessing the interface.

With run_as disabled, create a mapping rule in the Wazuh API for the Open Distro admin user. From the WUI it is quite simple, just go to the wazuh>security>roles_mapping section and create a new mapping, giving the admin role to the Open Distro admin user. After that you can enable run_as again.

This way you will have the admin user with full permissions and the A and B users with restricted access.

Best regards,

WazuhAlfonso Ruiz-Bravo
Cloud computing engineer
WazuhThe Open Source Security Platform

Batsal Nepal

unread,
Jul 7, 2021, 4:30:37 AM7/7/21
to Alfonso Ruiz-Bravo, Wazuh mailing list
Hi Alfonso,
Thanks a million for that information.
Regards,
Batsal Nepal
SIEM Engineer
phone: +977-014441540
mobile: +9779840171116
linkedin icon
logo
Baluwataar, Kathmandu
Nepal
vairav.net
We now provide Managed Cyber Security Operation Center Service.

The information contained in this message is intended for the addressee only and may contain classified information. If you are not the addressee, please delete this message and notify the sender; you should not copy or distribute this message or disclose its contents to anyone. Any views or opinions expressed in this message are those of the individual(s) and not necessarily of the organization. No reliance may be placed on this message without written confirmation from an authorised representative of its contents. No guarantee is implied that this message or any attachment is virus free or has not been intercepted and amended.

Reply all
Reply to author
Forward
0 new messages