Cacti / cacti

Cacti ™
http://www.cacti.net
GNU General Public License v2.0
1.62k stars 403 forks source link

Multi AD auth to cacti usergroup enhancement #572

Open g1augusto opened 7 years ago

g1augusto commented 7 years ago

It would be good to redesign the mutliple AD to cacti usergroup integration.

Currently every single AD realm can match a group membership in LDAP but this allows for that specific membership to cacti internal usergroups, unless multiple Realms with each one a different AD group membership is configured (and the user should select the right one :/ )

A better approach would be to allow for a user authentication matching AD domain membership and to create authorization rules for specific group membership in AD to match cacti internal groups.

This way the whole process could be automated and users could login selecting just their domain and having cacting handling the permissions in the background with a 1:1 reference to the AD structure

ronytomen commented 7 years ago

Do you want to make an attempt to update the code and submit a pull request?

netniV commented 6 years ago

This may also fall in line with a bug #1083 where different groups can lead to different redirects if you are part of multiple groups. As I've just gone through a lot of the auth code for #1122 I'll give this some thought.

g1augusto commented 6 years ago

Hi everyone,

Did you had a chance to integrate or plan to include this feature in CACTI 1.2 ?

It would help a lot on our rollout of CACTI in our infrastructure, otherwise we will be forced to handle CACTI access in parallel to our AD management.

netniV commented 6 years ago

I didn't get around to looking at this as a feature when I updated the mutli-auth code. The primary reason is that we would have to do several things such as:

So, as you can see, I gave it some thought especially with all the changes I made for #1122 but being fairly new to changing things around here, I didn't want to rush into this one and I do apologise that I let it drop off my radar so I didn't update it with my above ramblings :)

g1augusto commented 6 years ago

Thanks for your reply,

My suggestion would be to perform a gr

Flip the code on its head so that post user authentication it retrieves ALL groups a user is a member of. Otherwise we have to leave the code as is, but add LDAP fields to each group for performing a search base, context, etc. Bu this could lead to finding the same LDAP group twice for two different cacti groups.

When performing the compare do we use the underlying context name or display name of each group and hold that against the cacti groups.

Since AD management occurs outside of Cacti, this would mean dynamically changing the userlist of a group on the fly. That would mean placing Cacti into a "consistent query" mode where all pages (since they all deal with permissions) would need to be constantly checking against the AD for permissions. So, rather than one call at the start to see if the user is valid, you have to check on every page whether the user is still part of that cacti group by querying to LDAP.

Do we allow only one LDAP group per Cacti group? Or do we allow multiple LDAP to one group? However, group BOB of realm 3 (Live AD) may be used for a completely different purpose than group BOB of realm 6 (Customer AD)

Do we run an import process that pulls in all the LDAP groups and disables those it can't find any more. How do we define not find? If the AD no longer responds and after how many retries? If the AD query was succesful, but the group was not in the list?

(1) My suggestion is to run the retrieval of the CACTI groups only at the first login (so if a user is not already in the local CACTI database), then only at that point perform a search that following some TBD CACTI group rules to match AD Group membership <-> CACTI group membership Once this is done an user could be managed within CACTI as it is now.

CACTI groups should be referenced to more than one AD group membership as several subset of an organization may have the same access requirements.

(2) Another more complex approach is to retrieve the groups a member belongs to at each login and proceed on adding that user to all related CACTI group membership that matches (obviously also CACTI should work allowing access from all permissive rules from all group memberships, but I guess it works already this way). Honestly I think this approach may be too much taxing the authentication process (each time and LDAP search and group membership assignation etc) and it may really be used seldom as I believe that normally withing a company structure people do not change roles so often and if so not all together.

I would go for 1 if you think it's doable.

netniV commented 6 years ago

On the security side, it has been noted that we should try and reduce the timings of some of the security functions. Point (2) does kinda of address that as it couples onto the idea I had had of having a user object with a list of groups already in memory with a hash that validates this against the user_auth table. That way if the hash changes, it could be reloaded at that point.

It has the advantage that the permissions are already in memory and do not need a DB call everytime a peice of code has to verify them. But it means quite a revamp to the system so unlikely in the short term.

So, I think for now we should park that idea.

Moving to the original point, there are a couple of flaws with that system but it is easier to implement. Currently (if you setup your LDAP configuration the way I have), you can make it require a specific LDAP group to grant access. You can make use of the multiple domains, to create a realm per group. That means a specific user can be removed by the AD admin, and it removes that access. Works OK, no perfect since you have to define a template user with default permissions but it's manageable.

So, my thoughts are to achieve your proposal, we would additionally need

This is less work and could be migrated at a later point to something better. However, I think @cigamit or others may want to weigh in on that change.

cigamit commented 6 years ago

Well, what you could do is the following. It's pretty simple actually.

Instead of having the users wait for a login while we retrieve all that data, and it could take a while, the second way we 'could' do this is to periodically bind to the domains using a read only service account and retrieve user group memberships associated to the Cacti groups, and update in batch.

The downside of that is that we would have to cache credentials either in the database or in a static config file readable by only root/apache.

I'm not a big fan of storing credentials in static files, but I'm also not a fan of storing passwords in a database either. I guess if it's a service account, it's potentially no biggie.

If you do not associate the user groups to the ldap domains, we use the existing behavior. Mixed behavior would also be supported in either case.

What do you guys think?

netniV commented 6 years ago

Don’t we already store an ldap username/password ?

cigamit commented 6 years ago

Yes, but it is optional. Given that we are already down that road, what are your thoughts?

netniV commented 6 years ago

Well I think as far as an AD LDAP connection goes it’s not optional because anonymous connections are prevented by default. Other LDAP providers can be different and ultimately it comes down to how the sysadmin of the LDAP environment wants you to connect.

So, I think we just reuse what we already had but extend it to groups. We should probably encrypt the storage of that password if it’s not already done so to prevent it leaking in a MySQL dump.

I’ll do some quick tests over retrieving a users, groups and user groups how long it takes. Ultimately, I think the easiest part is to give ‘membership’ for an LDAP group to a cacti group. If we cache various data but use a TTL like you suggest this should give a balanced approach.

So to summarise was what I think we are agreeing towards:

Would we need a way to differentiate so an admin doesn’t mess up the membership of a user added automatically vs one who is manually done?

g1augusto commented 6 years ago

if using LDAP groups, should they also be allowed to manually add members? For example, you might want a local user for outside contractors, suppliers or customers which you don’t want in the AD

I think there should be a a mix of LDAP users and local users for each CACTI group, the discriminator from processing the LDAP membership or not for a users should be if the user has a local authentication or an LDAP/AD domain authentication. Makes sense?

g1augusto commented 6 years ago

Another comment is that the LDAP mapping should be an option per user if possible so that there can be a mix of LDAP authentication with pre assigned cacti group or a way to override it

cigamit commented 6 years ago

Moving pretty quickly on this. I completed the functional design over night and have performed some mock-ups below:

The first image is of the User Group Edit page. It shows a new 'Synchonization' tab. This is where we will make the associations with the various groups and types.

usergroupnewtab

The next image is of the User Group Members tab. We will still be allowed to add local users even when Synchornization is enabled. Member types include System, Linux, Domain, and if a Domain, it will be from the System Domain, or the Domain name specified. Added Last Login for color. Users who have never logged in of course will show no login date.

If a user's membership is from a Synchronized group, you will be unable to remove that user. Locally defined users will of course be able to be deleted.

usergroupmembers

Lastly the Synchronization tab. This tab, we will be able to force synchronization and be able to add/remove Groups to the synchronization list. Again, the types are Linux (getent), and LDAP/AD. Also adding the 'Last Sync', and I guess, though it's not there, the status of synchronization if one is in progress.

usergroupsynchonization

Table schema, polling, caching, API, editing sync groups have not been started. Comments?

netniV commented 6 years ago

Looks good from the screenshots. I presume this will need some testing since it'll changes things, will there be a branch for that ?

cigamit commented 6 years ago

I'm planning on putting the functional GUI and the core of the data collector in the 1.2 branch once I have it functional. Then, I need someone to help with the bulk collection code and the API changes, I the caching that was discussed earlier. Are you in for that? I really don't have a good 'test' environment.

netniV commented 6 years ago

Yeah, I can do some tests and maybe even get some code together for the downloading.

netniV commented 6 years ago

One thing that's come from my initial glance, do we include Distribution Groups or just Security Groups? In the AD environment there are different types of groups but I'm not sure there is in a pure LDAP environment.

cigamit commented 6 years ago

If the query is going to be different for both and they are both required, we will need one more column for that, I'll leave that to you. Whatever makes sense. The Linux one is easy though ;) (getent group, and it can be integrated into AD using RFC2307, or Microsoft's Identity Management for Unix, Centrify, VAS, you name it)

Maybe jhonnyx82 can comment on LDAP? You out there?

netniV commented 6 years ago

It basically is part fo the ldap_search functionality where you can specify leave off the filter or one of the following:

SECURITY_GLOBAL_GROUP = 268435456;
DISTRIBUTION_GROUP = 268435457;
SECURITY_LOCAL_GROUP = 536870912;
DISTRIBUTION_LOCAL_GROUP = 536870913;

using the filter such as:

$filter = "(&(objectCategory=group)(samaccounttype=" . SECURITY_GLOBAL_GROUP . "))";
cigamit commented 6 years ago

So, we need to have a dropdown in the Syncronization page. Makes sense. We need feeback relative to LDAP.

cigamit commented 6 years ago

Talked to Rony about encryption. The good news, we have an RSA public/private key in the database. The bad news... We will take the encryption discussion in baby steps.