ReadonlyRest login fail hook function

I met a problem that my customers hope me to count their members’ failed login times and it is for internal auditing.

Nowadays, I use the Kibana message logs to filter whether there is any fail login message or not to count the times. However, it is inefficient. Is there any webhook function for readonlyrest_kbn so that I can automatically count the failed login times when the user login with the wrong password and the Readonlyrest can notify my program? Or will you release this feature in the future? Thank you!

Hello @Jstyle0302, why not using ROR audit logging for this?

You can then query all the readonlyrest-audit-* indices to count the events where the “path” JSON field starts with “/_readonlyrest/metadata/current_user” and the “final_state” JSON field is not “ALLOWED”

Hi Simone,
Can I get the Login failed username from the message? I need to count who always login failed and count the times for every member. Below is the message I got from the readonlyrest_audit-* indices and in that time I login with username kibana.

{
  "_index": "readonlyrest_audit-2019-12-20",
  "_type": "ror_audit_evt",
  "_id": "1476815324-1950558446#9632507",
  "_version": 1,
  "_score": null,
  "_source": {
    "headers": [
      "Connection",
      "authorization",
      "Content-Length",
      "x-dynatrace",
      "Host"
    ],
    "acl_history": "[::KIBANA-SRV::-> RULES:[auth_key_sha256->false], RESOLVED:[]], [::LOGSTASH::-> RULES:[auth_key_sha256->false], RESOLVED:[]], [superuser-> RULES:[groups->false], RESOLVED:[]], [guest-> RULES:[groups->false], RESOLVED:[]], [newgroup_admin_filter-> RULES:[groups->false], RESOLVED:[]], [newgroup_admin_auth-> RULES:[groups->false], RESOLVED:[]], [newgroup_member_filter-> RULES:[groups->false], RESOLVED:[]], [newgroup_member_auth-> RULES:[groups->false], RESOLVED:[]], [nspectrum_admin_filter-> RULES:[groups->false], RESOLVED:[]], [nspectrum_admin_auth-> RULES:[groups->false], RESOLVED:[]], [nspectrum_member_filter-> RULES:[groups->false], RESOLVED:[]], [nspectrum_member_auth-> RULES:[groups->false], RESOLVED:[]]",
    "origin": "192.168.0.141/32",
    "match": false,
    "final_state": "FORBIDDEN",
    "destination": "192.168.0.111/32",
    "task_id": 9632507,
    "type": "RRAdminRequest",
    "req_method": "GET",
    "path": "/_readonlyrest/metadata/current_user",
    "indices": [],
    "@timestamp": "2019-12-20T02:44:47Z",
    "content_len_kb": 0,
    "processingMillis": 9,
    "action": "cluster:admin/rradmin/refreshsettings",
    "block": "default",
    "id": "1476815324-1950558446#9632507",
    "content_len": 0
  },
  "fields": {
    "@timestamp": [
      "2019-12-20T02:44:47.000Z"
    ]
  },
  "highlight": {
    "path": [
      "/@kibana-highlighted-field@_readonlyrest@/kibana-highlighted-field@/@kibana-highlighted-field@metadata@/kibana-highlighted-field@/@kibana-highlighted-field@current_user@/kibana-highlighted-field@"
    ],
    "final_state": [
      "@kibana-highlighted-field@FORBIDDEN@/kibana-highlighted-field@"
    ]
  },
  "sort": [
    1576809887000
  ]
}

@Jstyle0302 yeah sure, you can enable advanced audit logging so you can see inside the HTTP request body.

Another solution would be to create a custom audit logger class, and inspect the body of the request only if the “path” starts with “/_readonlyrest/metadata/current_user” etc.
The code could then find the username field in the body, and add a custom field to the log event “username_login_attempt” or something like that.

@sscarduzio is it possible for us to export the log into logstash and then parse them instead of using the scala or java?

By the way, even though I opened the advanced audit logging configurations, audit_collector and audit_serializer, I could not see the failed login username from the logs either.

Below is one of my failed login logs and in this case I used username with kibana to login and I did not see any related information from this log.

{
  "_index": "readonlyrest_audit-2019-12-23",
  "_type": "ror_audit_evt",
  "_id": "1371261629-177955394#202522",
  "_version": 1,
  "_score": null,
  "_source": {
    "headers": [
      "Connection",
      "Content-Length",
      "authorization",
      "Host"
    ],
    "acl_history": "[::KIBANA-SRV::-> RULES:[auth_key_sha256->false], RESOLVED:[]], [::LOGSTASH::-> RULES:[auth_key_sha256->false], RESOLVED:[]], [superuser-> RULES:[groups->false], RESOLVED:[]], [guest-> RULES:[groups->false], RESOLVED:[]], [kevin_admin_filter-> RULES:[groups->false], RESOLVED:[]], [kevin_admin_auth-> RULES:[groups->false], RESOLVED:[]], [kevin_member_filter-> RULES:[groups->false], RESOLVED:[]], [kevin_member_auth-> RULES:[groups->false], RESOLVED:[]], [newgroup_admin_filter-> RULES:[groups->false], RESOLVED:[]], [newgroup_admin_auth-> RULES:[groups->false], RESOLVED:[]], [newgroup_member_filter-> RULES:[groups->false], RESOLVED:[]], [newgroup_member_auth-> RULES:[groups->false], RESOLVED:[]]",
    "origin": "192.168.0.141/32",
    "match": false,
    "final_state": "FORBIDDEN",
    "destination": "192.168.0.141/32",
    "task_id": 202522,
    "type": "RRAdminRequest",
    "req_method": "GET",
    "content": "",
    "path": "/_readonlyrest/metadata/current_user",
    "indices": [],
    "@timestamp": "2019-12-23T09:45:17Z",
    "content_len_kb": 0,
    "processingMillis": 4,
    "action": "cluster:admin/rradmin/refreshsettings",
    "block": "default",
    "id": "1371261629-177955394#202522",
    "content_len": 0
  },
  "fields": {
    "@timestamp": [
      "2019-12-23T09:45:17.000Z"
    ]
  },
  "highlight": {
    "path": [
      "/@kibana-highlighted-field@_readonlyrest@/kibana-highlighted-field@/@kibana-highlighted-field@metadata@/kibana-highlighted-field@/@kibana-highlighted-field@current_user@/kibana-highlighted-field@"
    ],
    "final_state": [
      "@kibana-highlighted-field@FORBIDDEN@/kibana-highlighted-field@"
    ]
  },
  "sort": [
    1577094317000
  ]
}

Many thanks!

Hey, I just checked in the code: in our Kibana plugin we are actually sending the credentials as basic auth. So the username is in the “Authorization” header value. The header values are present in audit logs only when the ES root logger is in debug mode, which should not be active in production, as very verbose.

To override this behaviour you’d need a custom serializer like the ones in Java / Scala.
Do you need our help to make one?

@sscarduzio Awesome! If you can help us make it, it will strongly reduce our burden and bring us a big favor. Could you help us to record who log in the Kibana and the final_state for this login in the readonlyrest_audit-* log? Thank you!

Hi @Jstyle0302
Try putting this jar in $ES_HOME/plugins/readonlyrest/

And in the config/readonlyrest.yml

readonlyrest:
    audit_collector: true
    audit_serializer: "tech.beshu.ror.audit.instances.ScalaCustomAuditLogSerializer"
....

@sscarduzio Sorry, this link has already expired. Could you give me a new one? Thank you!

Here you go

Hi @sscarduzio
Thank, it works!

1 Like

@sscarduzio
I also want to download this file, but this link has already expired. Could you give me a new one? Thank you!

I made it public now:

https://readonlyrest-data.s3-eu-west-1.amazonaws.com/tmp/ror-cust-serializer-basic-auth-failure-log-user-with-query.jar

Hey @winnie! Nice to see you around! Greetings to Taiwan! :slight_smile: