codingchili/kibana-mithril

AD LDAP Configuration

Grunticus03 opened this issue · 17 comments

Excellent looking plugin, however I am running into an error in the configuration. I've got it configured as follows:

{
  "storage": "ldap",
  "two-factor": {
    "enabled": false,
    "length": 6
  },
  "proxy": {
    "enabled": false,
    "port": 7575,
    "remote": "localhost:5601"
  },
  "authentication": {
    "kbnVersion": "6.6.0",
    "cookie": {
      "ttl": 1209600,
      "path": "/",
      "encoding": "none",
      "isSecure": false,
      "isHttpOnly": true,
      "clearInvalid": true,
      "strictHeader": true
    },
    "secret": null
  },
  "file": {
    "filename": "users.json"
  },
  "ldap": {
    "url": "ldap://SERVERIP:389",
    "admin": {
      "dn": "cn=Username,ou=level2,ou=level1,dc=domain,dc=com",
      "password": "UserPassword"
    },
    "search": {
      "scope": "sub",
      "user-dn": "ou=accounts,ou=level2,ou=level1,dc=domain,dc=com",
#      "group-dn": "ou=groups,ou=system"
    }
  },
  "mongodb": {
    "remote": "mongodb://localhost/plugin"
  }
}

I get the following error on Kibana startup:

{"type":"log","@timestamp":"2019-02-21T10:36:49-06:00","tags":["fatal","root"],"pid":404,"message":"SyntaxError: Unexpected token # in JSON at position 873\n    at JSON.parse (<anonymous>)\n    at load (D:/ElasticStack/Apps/Kibana/6.6/plugins/kibana-mithril/src/config.js:17:19)\n    at Object.<anonymous> (D:/ElasticStack/Apps/Kibana/6.6/plugins/kibana-mithril/src/config.js:21:1)\n    at Module._compile (internal/modules/cjs/loader.js:688:30)\n    at loader (D:\\ElasticStack\\Apps\\Kibana\\6.6\\node_modules\\babel-register\\lib\\node.js:144:5)\n    at Object.require.extensions.(anonymous function) [as .js] (D:\\ElasticStack\\Apps\\Kibana\\6.6\\node_modules\\babel-register\\lib\\node.js:154:7)\n    at Module.load (internal/modules/cjs/loader.js:598:32)\n    at tryModuleLoad (internal/modules/cjs/loader.js:537:12)\n    at Function.Module._load (internal/modules/cjs/loader.js:529:3)\n    at Module.require (internal/modules/cjs/loader.js:636:17)\n    at require (internal/modules/cjs/helpers.js:20:18)\n    at Object.<anonymous> (D:/ElasticStack/Apps/Kibana/6.6/plugins/kibana-mithril/src/authentication/auth.js:9:16)\n    at Module._compile (internal/modules/cjs/loader.js:688:30)\n    at loader (D:\\ElasticStack\\Apps\\Kibana\\6.6\\node_modules\\babel-register\\lib\\node.js:144:5)\n    at Object.require.extensions.(anonymous function) [as .js] (D:\\ElasticStack\\Apps\\Kibana\\6.6\\node_modules\\babel-register\\lib\\node.js:154:7)\n    at Module.load (internal/modules/cjs/loader.js:598:32)\n    at tryModuleLoad (internal/modules/cjs/loader.js:537:12)\n    at Function.Module._load (internal/modules/cjs/loader.js:529:3)\n    at Module.require (internal/modules/cjs/loader.js:636:17)\n    at require (internal/modules/cjs/helpers.js:20:18)\n    at Object.<anonymous> (D:/ElasticStack/Apps/Kibana/6.6/plugins/kibana-mithril/src/api/filter.js:12:24)\n    at Module._compile (internal/modules/cjs/loader.js:688:30)\n    at loader (D:\\ElasticStack\\Apps\\Kibana\\6.6\\node_modules\\babel-register\\lib\\node.js:144:5)\n    at Object.require.extensions.(anonymous function) [as .js] (D:\\ElasticStack\\Apps\\Kibana\\6.6\\node_modules\\babel-register\\lib\\node.js:154:7)\n    at Module.load (internal/modules/cjs/loader.js:598:32)\n    at tryModuleLoad (internal/modules/cjs/loader.js:537:12)\n    at Function.Module._load (internal/modules/cjs/loader.js:529:3)\n    at Module.require (internal/modules/cjs/loader.js:636:17)"}

I'm not well versed in the language but it looks like it isn't happy with the path setting in config.json? I have not made any modifications to the users.json file as I'm unsure of what exactly its supposed to contain. I've currently got MFA set to disable as I just want to verify LDAP authentication is up and running.

Hello,

In JSON '#' is not used to comment out a line, default is to not support comments in JSON files.
I know there is an extension that allows '//' to be used for comments, but it's not enabled.

Please remove '#' from this:

#      "group-dn": "ou=groups,ou=system"

If you use LDAP the users.json is used to store the two-factor secret when MFA is enabled.
If you don't have MFA enabled, users.json is not used. It will be updated the first time
an user sets up their shared secret.

Thanks for submitting an issue.

Please update to 1.2.1 if you want to use LDAP and 2FA at the same time.

Just fixed an issue with the key setup.

Looks like removing the commented line resolved that particular issue. However, there appears to be another issue, though I'm unsure of whether its my config or the plugin. When starting Kibana, I get the following error:

InvalidCredentialsError: 80090308: LdapErr: DSID-0C090400, comment: AcceptSecurityContext error, data 52e, v1db1

Researching the error, specifically data 52e, indicates that I have an invalid password. I've verified I am using the correct password for the account and event reset the account password to the value I am using. The only entry in Kibana.log is

{"type":"log","@timestamp":"2019-02-21T15:09:28-06:00","tags":["plugin","warning"],"pid":4364,"path":"D:\\ElasticStack\\Apps\\Kibana\\6.6\\src\\legacy\\core_plugins\\ems_util","message":"Skipping non-plugin directory at D:\\ElasticStack\\Apps\\Kibana\\6.6\\src\\legacy\\core_plugins\\ems_util"}

Maybe I am misunderstanding the config settings.

Under LDAP:

  • Admin - The LDAP account that will be performing the query?
  • Admin DN is in the form of 'cn=useraccount,ou=ou1,dc=domain'?
  • Admin Password is the admin DN account secret in plaintext?
  • Search User-DN - This is user or ou containing users authorized to login? Using the same syntax as admin DN?
  • Search Group-DN - This is a group authorized to login? Using the same syntax as admin DN?

Yes - except one thing, you don't need to be in the "group dn" to be allowed to login, it will be used in the future to manage access to spaces/dashboards.

How is your password stored in the AD server? Hash algorithm?

I only tested it with a plaintext password. I'm going to do another test tomorrow.

What kind of AD server are you running? The plug-in is tested with Apache DS.

I've seen the warning too, should not affect the plug-in

Right I understood the difference on the memberships. This is on Microsoft Active Directory, I assume the password is stored as a hash but I am under the assumption that the LDAP query automatically performs the hashing operation.

I had already tested with plaintext and SHA256, it's working as expected.

I tested setting the dn of the admin config to "cn=username,ou=system" and it didn't work, nor with "sn=role,ou=system".

For some reason it's only able to authenticate when i set it to "uid=username,ou=system". In the other cases it fails to authenticate because it cannot find the user entry.

Could you try with uid instead of cn? if you have it on your user entry. do you need dc and both level1 and level2? I don't think using cn for the admin account is right, as it's not guaranteed to be unique.

If you can't get it working still, I'll try and setup Microsoft Active Directory.

I have tried it using uid=accountname,ou=containingou,dc=domain,dc=tld for the admin dn with the secret in plaintext, still get the same error. I also tried using just uid=accountname and came up with the same error.

thanks alot for the info, I'll try and reproduce it as soon as possible.

I've setup windows server 2019 with AD/LDAP in a hyper-v.

  • using ldp.exe I am able to connect and bind with the admin username.
  • using Apache Directory Studio I am able to connect but not bind.

LDAP: Error code 49, LdapErr: DSID-0c09041C comment: AcceptSecurityContext, data 52e, v4563.

Looks like the same error.

While testing this I realized that 52e is a wildly misleading error code, it's defined as 'invalid credentials'. But it appears if the bind DN is not 100% correct.

To figure out the correct bind DN I used Apache Directory Studio

  1. set up a connection
  2. test the connection
  3. set up authentication
  4. choose simple authentication
  5. enter the USERNAME only and not a BIND DN, for me it was 'ROOT\Administrator' where ROOT is my domain name.
  6. enter the bind password and check the authentication.
  7. if authentication works: find the user in the tree
  8. right click the principal and click "copy DN".
  9. this gave me "CN=Administrator,CN=Users,DC=root,DC=io"
  10. Set up a new connection and use the BIND DN to authenticate = worked.

I guess the problem I had was specifying the group with OU=Users instead of CN=Users. There seems to be a difference there with the AD server I was using before.

Success...with a caveat.

  1. Open ADUC (Active Directory Users and Computers)
  2. Find authenticating user.
  3. Right-click user object>Select Attribute Editor Tab (If not visible, in main ADUC window select View>Advanced Features)
  4. Copy dn attribute
  5. Paste dn from AD into config.json.
    Here's the caveat, if the dn has a \ in the name, an error is thrown. FATAL SyntaxError: Unexpected token , in JSON at position 607. For example, my account DN is CN=LastName\, FirstName,OU=org,DC=test,DC=net. The workaround for this was to simply remove the \ and I was able to log in.

The only other issue I have now is I can't add users or authenticate with any user account except the default username\password. In the config.json file under search, I did omitted the group-dn setting and configured the user-dn to be dc=test,dc=net. When I go into the Mithril section in Kibana, all I see is the below image. I assumed the two dn settings under search worked as follows:

user-dn: specify an OU containing users authorized to login
group-dn: specify a group containing users authorized to login
These settings can be exclusive or in combination to form a desired authentication plan.

image

Additional Testing

Domain: test.net
Domain Controller: DC1 (192.168.1.1)
Directory Structure

  • test.net
    • Org
      • Groups
        • KibanaAccess (Group Object)
      • Svc Accounts
        • Auth, LDAP (User Object) - Username: svc_ldap
      • Users
        • User, Test (User Object) - Username: testuser

Mithril LDAP Account DN CN=Auth, LDAP,OU=svc accounts,OU=org,DC=test,DC=net
Kibana User DN CN=User, Test,CN=users,OU=org,DC=test,DC=net
Test User Group Membership CN=KibanaAccess,OU=Groups,OU=org,DC=test,DC=net

LDAP Configuration:

    "ldap": {
        "url": "ldap://192.168.1.1:389",
        "admin": {
            "dn": "CN=Auth, LDAP,OU=svc accounts,OU=org,DC=test,DC=net",
            "password": "ItsAs5cr5t"
        },
        "search": {
            "scope": "sub",
            "user-dn": "CN=users,OU=org,DC=test,DC=net",
            "group-dn": "CN=KibanaAccess,OU=Groups,OU=org,DC=test,DC=net"
        }
    }

Attempted authentication with the following username AD attributes: sAMAccountName, UserPrincipalName, Pre-Windows 2000 user logon name (testuser, testuser@test.net, test\testuser)

@wwalker0307
Do you have the following error when click login?

image
Did you use linux or windows?

In json \ backslash is a control character, it can be escaped with , for example "CN=LastName\\" in JSON is read as CN=LastName.

_group-dn: specify a group containing users authorized to login_

group-dn is not used for authentication - it will be used in the future to determine which spaces/dashboards a user is able to view. it's not yet implemented.

does your AD accounts actually have the uid attribute? It's not set in my Microsoft AD, but it's set in my Apache AD. Maybe we should be querying for the sAMAccountName instead of the uid for Microsoft ADs?

The last configuration you posted looks good.

Could you try editing kibana/plugins/kibana-mithril/src/authentication/ldap.js ?

Replace

  • filter: new LDAP.filters.EqualityFilter({attribute: 'uid', value: username})

with

  • filter: new LDAP.filters.EqualityFilter({attribute: 'sAMAccountName', value: username})

If it works I will make the attribute for matching the username configurable. Alternatively, you could try adding the uid attribute to a single user for testing.

Microsoft Active Directory doesn't have a UID attribute and modifying AD to include custom attributes is generally frowned upon and could cause support issues with Microsoft. If memory serves, samaccountname is a unique account attribute, it's generally used by most authentication providers as a means to uniquely identify a user.

I think being able to customize the attribute that's used for username would be highly desirable by many. For example, some organizations may standardize on users logging in with email address, so being able to say, look at user's mail attribute would align with that organization.

I've modified ldap.js as requested and it still does not work. Is there any kind of additional logging that we can enable, like verbose logging on the LDAP request to see it in action?

I am ingesting DC Security logs into my ElasticStack which displays user login attempts and I'm not even seeing the auth request come in.

It could work now,thanks very much.

@codingchili Have you had any time to investigate this issue further?

Hi,

I'm working on improving the configurability and assuring quality on Microsoft ADs. Error handling has been improved to make sure errors are logged.

There is currently a blocking issue with group discovery not finding any groups.