codingchili / kibana-mithril

Kibana nodejs/hapi plugin adds support for LDAP and 2-factor OTP authentication to dashboards.
https://kibana-mithril.com/
MIT License
51 stars 24 forks source link

AD LDAP Configuration #44

Open Grunticus03 opened 5 years ago

Grunticus03 commented 5 years ago

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.

codingchili commented 5 years ago

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.

codingchili commented 5 years ago

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.

Grunticus03 commented 5 years ago

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:

codingchili commented 5 years ago

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

Grunticus03 commented 5 years ago

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.

codingchili commented 5 years ago

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.

Grunticus03 commented 5 years ago

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.

codingchili commented 5 years ago

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

codingchili commented 5 years ago

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

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.

Grunticus03 commented 5 years ago

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

Grunticus03 commented 5 years ago

Additional Testing

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

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)

tuohaibei commented 5 years ago

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

image Did you use linux or windows?

codingchili commented 5 years ago

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

with

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.

Grunticus03 commented 5 years ago

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.

tuohaibei commented 5 years ago

It could work now,thanks very much.

Grunticus03 commented 5 years ago

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

codingchili commented 5 years ago

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.