Re: [Freeipa-devel] Generate report of user access levels on each system

2016-05-09 Thread Jerel Gilmer
Thanks Jakub.  My goal for the scripts I wrote would be
to potentially address both:

https://fedorahosted.org/freeipa/ticket/3775

https://fedorahosted.org/sssd/ticket/2840

The scripts could be run centrally from an IdM server and produce a report
for all registered systems in under a few seconds. I have over 1100 systems
in my environment.

Using the 'ipa hbactest' to produce a similar report would take too long to
run.

Using the sssd cache on each systems would be a local approach that
couldn't be scaled in my environment.

The scripts allow for producing centralized system auditing and reporting.

One issue I noticed users run into is the need to produce reports of
system's allowed users and sudo rules. Although I can easily list the HBAC
and Sudo rules for each system, trying to pull a user list can be a tedious
task. That's where these scripts come in.
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Re: [Freeipa-devel] Generate report of user access levels on each system

2016-05-09 Thread Jakub Hrozek
On Sun, May 08, 2016 at 12:14:57PM -0400, Jerel Gilmer wrote:
> Hello all -
> 
> I've been using IdM and was tasked by my management with generating two
> system reports:
> 
> - List of what users have access to what services on each system
> - List of sudo rules for each system

The list of applicable HBAC rules and SUDO rules is resolved by SSSD.
This issue has come up before and we are tracking it in SSSD's tracker:
https://fedorahosted.org/sssd/ticket/2840
but unfortunately the current milestone under development got already
quite big, so it was bumped to the next version.

> 
> I did a lot of research but couldn't find a simple way to do this so I
> created scripts using ldapsearch calls that created the reports I needed.

What you can do for the access control attestation is to run ipa
hbactest. We don't have a similar tool for sudo. But looking into sssd's
cache with ldbsearch on the target host itself might give some idea.

> 
> I'm sending these out to the community for comment and for anyone that has
> similar requirements.
> 
> I've pasted the scripts below. If there are any issues with formatting, you
> can download the scripts from my Github (github
> com/jerelgilmer/freeipa-scripts)
> 
> Jerel Gilmer
> 
> --> server-access-report.py
> #!/usr/bin/python
> '''
>  2016 - March - 2
>  Author: Jerel Gilmer
> '''
> 
> import os
> import sys
> import ldap
> 
> def print_usage():
>  print "Usage: server-access-report.py "
>  print "This script generates the list of allowed users for each service
> defined in applicable HBAC rules.\n"
>  print " - System hostname; This can be the short name\n"
>  print "For report of all systems, use \'.\'\n"
>  print "Make sure to set the below variables in the script:"
>  print "\tDOMAIN: Domain component"
>  print "\tLDAP_SERVER: LDAP server to be queried"
>  print "\tLDAP_USER: LDAP user to query server; preferable a read-only
> account"
>  print "\tLDAP_PW: LDAP user's password\n"
>  sys.exit(1)
> 
> try:
>  server = str(sys.argv[1])
> except:
>  print_usage()
> 
> ## LDAP Connection Info and bind to the LDAP server
> ## Uncomment and set these variables to the appropriate values
> ## Below are examples
> #DOMAIN = "dc=sub,dc=example,dc=com"
> #LDAP_SERVER = "ldap://ipaserver1.sub.example.com;
> #LDAP_USER = "uid=user1,cn=users,cn=compat," + DOMAIN
> #LDAP_PW = "Password123"
> 
> try:
>  DOMAIN
>  LDAP_SERVER
>  LDAP_USER
>  LDAP_PW
> except:
>  print_usage()
> 
> l = ldap.initialize(LDAP_SERVER)
> 
> l.simple_bind_s(LDAP_USER,LDAP_PW)
> 
> ## LDAP Search Variables
> ## Base DN for LDAP Searches
> baseComputerDN = "cn=computers,cn=accounts," + DOMAIN
> baseGroupDN =  "cn=groups,cn=accounts," + DOMAIN
> baseUserDN = "cn=users,cn=accounts," + DOMAIN
> baseHBACDN = "cn=hbac," + DOMAIN
> baseHBACServicesDN = "cn=hbacservices,cn=hbac," + DOMAIN
> baseHBACServiceGroupsDN = "cn=hbacservicegroups,cn=hbac," + DOMAIN
> 
> ## Default LDAP SCOPE
> scope = ldap.SCOPE_SUBTREE
> 
> ## Filter for LDAP Searches
> compFilter = "(&(objectclass=ipahost)(fqdn=*" + server + "*))"
> hbacFilter = "(objectclass=ipahbacrule)"
> userFilter = "(objectclass=person)"
> groupFilter = "(objectclass=ipausergroup)"
> hbacServiceFilter = "(objectclass=ipahbacservice)"
> hbacServiceGroupsFilter = "(objectclass=ipahbacservicegroup)"
> 
> ## Attributes from LDAP Searches
> compAttributes =  ['memberOf', 'fqdn']
> hbacAttributes = ['memberUser', 'memberService', 'serviceCategory']
> userAttributes = ['uid']
> groupAttributes = ['member']
> hbacServiceAttributes = ['cn' , 'ipaUniqueID']
> hbacServiceGroupsAttributes = ['cn' , 'member']
> 
> ## Perform LDAP searches and store results into array
> ALL_HOSTS = l.search_s(baseComputerDN, scope, compFilter, compAttributes)
> 
> ALL_USERS = l.search_s(baseUserDN, scope, userFilter, userAttributes)
> 
> ALL_GROUPS = l.search_s(baseGroupDN, scope, groupFilter, groupAttributes)
> 
> ALL_HBACRULES = l.search_s(baseHBACDN, scope, hbacFilter, hbacAttributes)
> 
> ALL_HBACSERVICES = l.search_s(baseHBACServicesDN, scope, hbacServiceFilter,
> hbacServiceAttributes)
> 
> ALL_HBACSERVICEGROUPS = l.search_s(baseHBACServiceGroupsDN, scope,
> hbacServiceGroupsFilter, hbacServiceGroupsAttributes)
> 
> # HBAC rules that apply to all servers
> hbacAllServersFilter = "(&(objectclass=ipahbacrule)(hostCategory=all))"
> HBACRULE_ALL_SERVERS = l.search_s(baseHBACDN, scope, hbacAllServersFilter,
> hbacAttributes)
> 
> ALL_HOSTS.sort()
> 
> def findUID(user):
>  uid = filter(lambda x: user in x, ALL_USERS)
>  return uid[0][1]['uid'][0]
> 
> def findGroupMembers(groupname):
>  if "cn=groups,cn" not in groupname:
>   pass
>  group = filter(lambda x: groupname in x, ALL_GROUPS)
>  try:
>   groupmembers = group[0][1]['member']
>  except:
>   groupmembers = ""
>  for user in groupmembers:
>   if "cn=groups,cn" in user:
>for i in findGroupMembers(user):
> yield i
>   else:
>yield (findUID(user))
> 
> def findServiceName(service_name):
>  s = filter(lambda x: